/* Copyright (C) 2020 Open Information Security Foundation
 *
 * You can copy, redistribute or modify this Program under the terms of
 * the GNU General Public License version 2 as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

use std::mem::transmute;
use crate::applayer::*;
use crate::core::{self, *};
use crate::dcerpc::parser;
use nom::error::ErrorKind;
use nom::number::Endianness;
use nom;
use std::cmp;

// Constant DCERPC UDP Header length
pub const DCERPC_HDR_LEN: u16 = 16;
// FIRST flag set on the packet
pub const DCERPC_UUID_ENTRY_FLAG_FF: u16 = 0x0001;

// Flag bits in connection-oriented PDU header

// Value to indicate first fragment
pub const PFC_FIRST_FRAG: u8 = 0x01;
// Value to indicate last fragment
pub const PFC_LAST_FRAG: u8 = 0x02;
// Cancel was pending at sender
pub const PFC_PENDING_CANCEL: u8 = 0x04;
pub const PFC_RESERVED_1: u8 = 0x08;
// supports concurrent multiplexing of a single connection.
pub const PFC_CONC_MPX: u8 = 0x10;
// only meaningful on `fault' packet; if true, guaranteed
//  call did not execute.
pub const PFC_DID_NOT_EXECUTE: u8 = 0x20;
// `maybe' call semantics requested
pub const PFC_MAYBE: u8 = 0x40;
// if true, a non-nil object UUID was specified in the handle, and
//  is present in the optional object field. If false, the object field
// is omitted.
pub const PFC_OBJECT_UUID: u8 = 0x80;

// Flag bits in first flag field in connectionless PDU header.
pub const PFCL1_RESERVED_01: u8 = 0x01; // Reserved for use by implementations
pub const PFCL1_LASTFRAG: u8 = 0x02; // If set, the PDU is the last fragment
                                     // of a multi-PDU transmission
pub const PFCL1_FRAG: u8 = 0x04; // If set, the PDU is a fragment
                                 // of a multi-PDU transmission
pub const PFCL1_NOFACK: u8 = 0x08; // If set, the receiver is not requested
                                   // to send a `fack' PDU for the fragment
pub const PFCL1_MAYBE: u8 = 0x10; // If set, the PDU is for a `maybe' request
pub const PFCL1_IDEMPOTENT: u8 = 0x20; // If set, the PDU is for
                                       // an idempotent request
pub const PFCL1_BROADCAST: u8 = 0x40; // If set, the PDU is for
                                      // a broadcast request
pub const PFCL1_RESERVED_80: u8 = 0x80; // Reserved for use by implementations

// Flag bits in second flag field in connectionless PDU header.
pub const PFCL2_RESERVED_01: u8 = 0x01; // Reserved for use by implementations
pub const PFCL2_CANCEL_PENDING: u8 = 0x02; // Cancel pending at the call end
pub const PFCL2_RESERVED_04: u8 = 0x04; // Reserved for future use
pub const PFCL2_RESERVED_08: u8 = 0x08; // Reserved for future use
pub const PFCL2_RESERVED_10: u8 = 0x10; // Reserved for future use
pub const PFCL2_RESERVED_20: u8 = 0x20; // Reserved for future use
pub const PFCL2_RESERVED_40: u8 = 0x40; // Reserved for future use
pub const PFCL2_RESERVED_80: u8 = 0x80; // Reserved for future use

pub const REASON_NOT_SPECIFIED: u8 = 0;
pub const TEMPORARY_CONGESTION: u8 = 1;
pub const LOCAL_LIMIT_EXCEEDED: u8 = 2;
pub const CALLED_PADDR_UNKNOWN: u8 = 3; /* not used */
pub const PROTOCOL_VERSION_NOT_SUPPORTED: u8 = 4;
pub const DEFAULT_CONTEXT_NOT_SUPPORTED: u8 = 5; /* not used */
pub const USER_DATA_NOT_READABLE: u8 = 6; /* not used */
pub const NO_PSAP_AVAILABLE: u8 = 7; /* not used */

// DCERPC Header packet types
pub const DCERPC_TYPE_REQUEST: u8 = 0;
pub const DCERPC_TYPE_PING: u8 = 1;
pub const DCERPC_TYPE_RESPONSE: u8 = 2;
pub const DCERPC_TYPE_FAULT: u8 = 3;
pub const DCERPC_TYPE_WORKING: u8 = 4;
pub const DCERPC_TYPE_NOCALL: u8 = 5;
pub const DCERPC_TYPE_REJECT: u8 = 6;
pub const DCERPC_TYPE_ACK: u8 = 7;
pub const DCERPC_TYPE_CL_CANCEL: u8 = 8;
pub const DCERPC_TYPE_FACK: u8 = 9;
pub const DCERPC_TYPE_CANCEL_ACK: u8 = 10;
pub const DCERPC_TYPE_BIND: u8 = 11;
pub const DCERPC_TYPE_BINDACK: u8 = 12;
pub const DCERPC_TYPE_BINDNAK: u8 = 13;
pub const DCERPC_TYPE_ALTER_CONTEXT: u8 = 14;
pub const DCERPC_TYPE_ALTER_CONTEXT_RESP: u8 = 15;
pub const DCERPC_TYPE_AUTH3: u8 = 16;
pub const DCERPC_TYPE_SHUTDOWN: u8 = 17;
pub const DCERPC_TYPE_CO_CANCEL: u8 = 18;
pub const DCERPC_TYPE_ORPHANED: u8 = 19;
pub const DCERPC_TYPE_RTS: u8 = 20;
pub const DCERPC_TYPE_UNKNOWN: u8 = 99;

pub fn dcerpc_type_string(t: u8) -> String {
    match t {
        DCERPC_TYPE_REQUEST => "REQUEST",
        DCERPC_TYPE_PING => "PING",
        DCERPC_TYPE_RESPONSE => "RESPONSE",
        DCERPC_TYPE_FAULT => "FAULT",
        DCERPC_TYPE_WORKING => "WORKING",
        DCERPC_TYPE_NOCALL => "NOCALL",
        DCERPC_TYPE_REJECT => "REJECT",
        DCERPC_TYPE_ACK => "ACK",
        DCERPC_TYPE_CL_CANCEL => "CL_CANCEL",
        DCERPC_TYPE_FACK => "FACK",
        DCERPC_TYPE_CANCEL_ACK => "CANCEL_ACK",
        DCERPC_TYPE_BIND => "BIND",
        DCERPC_TYPE_BINDACK => "BINDACK",
        DCERPC_TYPE_BINDNAK => "BINDNAK",
        DCERPC_TYPE_ALTER_CONTEXT => "ALTER_CONTEXT",
        DCERPC_TYPE_ALTER_CONTEXT_RESP => "ALTER_CONTEXT_RESP",
        DCERPC_TYPE_AUTH3 => "AUTH3",
        DCERPC_TYPE_SHUTDOWN => "SHUTDOWN",
        DCERPC_TYPE_CO_CANCEL => "CO_CANCEL",
        DCERPC_TYPE_ORPHANED => "ORPHANED",
        DCERPC_TYPE_RTS => "RTS",
        DCERPC_TYPE_UNKNOWN => "UNKNOWN",
        _ => {
            return (t).to_string();
        }
    }
    .to_string()
}

pub fn get_resp_type_for_req(t: u8) -> u8 {
    match t {
        DCERPC_TYPE_REQUEST => DCERPC_TYPE_RESPONSE,
        DCERPC_TYPE_BIND => DCERPC_TYPE_BINDACK,
        DCERPC_TYPE_ALTER_CONTEXT => DCERPC_TYPE_ALTER_CONTEXT_RESP,
        _ => DCERPC_TYPE_UNKNOWN,
    }
}

pub fn get_req_type_for_resp(t: u8) -> u8 {
    match t {
        DCERPC_TYPE_RESPONSE => DCERPC_TYPE_REQUEST,
        DCERPC_TYPE_BINDACK => DCERPC_TYPE_BIND,
        DCERPC_TYPE_ALTER_CONTEXT_RESP => DCERPC_TYPE_ALTER_CONTEXT,
        _ => DCERPC_TYPE_UNKNOWN,
    }
}

#[derive(Debug)]
pub struct DCERPCTransaction {
    pub id: u64, // internal transaction ID
    pub ctxid: u16,
    pub opnum: u16,
    pub first_request_seen: u8,
    pub call_id: u32, // ID to match any request-response pair
    pub frag_cnt_ts: u16,
    pub frag_cnt_tc: u16,
    pub endianness: u8,
    pub stub_data_buffer_ts: Vec<u8>,
    pub stub_data_buffer_tc: Vec<u8>,
    pub stub_data_buffer_reset_ts: bool,
    pub stub_data_buffer_reset_tc: bool,
    pub req_done: bool,
    pub resp_done: bool,
    pub req_lost: bool,
    pub resp_lost: bool,
    pub req_cmd: u8,
    pub resp_cmd: u8,
    pub activityuuid: Vec<u8>,
    pub seqnum: u32,
    pub tx_data: AppLayerTxData,
    pub de_state: Option<*mut core::DetectEngineState>,
}

impl DCERPCTransaction {
    pub fn new() -> DCERPCTransaction {
        return DCERPCTransaction {
            id: 0,
            ctxid: 0,
            opnum: 0,
            first_request_seen: 0,
            call_id: 0,
            frag_cnt_ts: 0,
            frag_cnt_tc: 0,
            endianness: 0,
            stub_data_buffer_ts: Vec::new(),
            stub_data_buffer_tc: Vec::new(),
            stub_data_buffer_reset_ts: false,
            stub_data_buffer_reset_tc: false,
            req_done: false,
            resp_done: false,
            req_lost: false,
            resp_lost: false,
            req_cmd: DCERPC_TYPE_REQUEST,
            resp_cmd: DCERPC_TYPE_RESPONSE,
            activityuuid: Vec::new(),
            seqnum: 0,
            tx_data: AppLayerTxData::new(),
            de_state: None,
        };
    }

    pub fn free(&mut self) {
        match self.de_state {
            Some(state) => {
                sc_detect_engine_state_free(state);
            }
            _ => {}
        }
    }

    pub fn get_req_ctxid(&self) -> u16 {
        self.ctxid
    }

    pub fn get_first_req_seen(&self) -> u8 {
        self.first_request_seen
    }

    pub fn get_req_opnum(&self) -> u16 {
        self.opnum
    }

    pub fn get_endianness(&self) -> u8 {
        self.endianness
    }
}

impl Drop for DCERPCTransaction {
    fn drop(&mut self) {
        self.free();
    }
}

#[derive(Debug)]
pub struct DCERPCRequest {
    pub ctxid: u16,
    pub opnum: u16,
    pub first_request_seen: u8,
}

#[derive(Debug, Clone)]
pub struct DCERPCUuidEntry {
    pub ctxid: u16,
    pub internal_id: u16,
    pub result: u16,
    pub uuid: Vec<u8>,
    pub version: u16,
    pub versionminor: u16,
    pub flags: u16,
}

impl DCERPCUuidEntry {
    pub fn new() -> DCERPCUuidEntry {
        return DCERPCUuidEntry {
            ctxid: 0,
            internal_id: 0,
            result: 0,
            uuid: Vec::new(),
            version: 0,
            versionminor: 0,
            flags: 0,
        };
    }
}

#[derive(Debug, PartialEq)]
pub struct Uuid {
    pub time_low: Vec<u8>,
    pub time_mid: Vec<u8>,
    pub time_hi_and_version: Vec<u8>,
    pub clock_seq_hi_and_reserved: u8,
    pub clock_seq_low: u8,
    pub node: Vec<u8>,
}

#[derive(Debug)]
pub struct DCERPCHdr {
    pub rpc_vers: u8,
    pub rpc_vers_minor: u8,
    pub hdrtype: u8,
    pub pfc_flags: u8,
    pub packed_drep: Vec<u8>,
    pub frag_length: u16,
    pub auth_length: u16,
    pub call_id: u32,
}

#[derive(Debug)]
pub struct DCERPCBind {
    pub numctxitems: u8,
    pub uuid_list: Vec<DCERPCUuidEntry>,
}

#[derive(Debug)]
pub struct BindCtxItem {
    pub ctxid: u16,
    pub uuid: Vec<u8>,
    pub version: u16,
    pub versionminor: u16,
}

#[derive(Debug, PartialEq)]
pub struct DCERPCBindAckResult {
    pub ack_result: u16,
    pub ack_reason: u16,
    pub transfer_syntax: Vec<u8>,
    pub syntax_version: u32,
}

#[derive(Debug)]
pub struct DCERPCBindAck {
    pub accepted_uuid_list: Vec<DCERPCUuidEntry>,
    pub sec_addr_len: u16,
    pub numctxitems: u8,
    pub ctxitems: Vec<DCERPCBindAckResult>,
}

#[derive(Debug)]
pub struct DCERPCState {
    pub header: Option<DCERPCHdr>,
    pub bind: Option<DCERPCBind>,
    pub bindack: Option<DCERPCBindAck>,
    pub transactions: Vec<DCERPCTransaction>,
    pub buffer_ts: Vec<u8>,
    pub buffer_tc: Vec<u8>,
    pub pad: u8,
    pub padleft: u16,
    pub bytes_consumed: u16,
    pub tx_id: u64,
    pub query_completed: bool,
    pub data_needed_for_dir: u8,
    pub prev_dir: u8,
    pub prev_tx_call_id: u32,
    pub clear_bind_cache: bool,
    pub ts_gap: bool,
    pub tc_gap: bool,
    pub ts_ssn_gap: bool,
    pub tc_ssn_gap: bool,
    pub ts_ssn_trunc: bool, /// true if Truncated in this direction
    pub tc_ssn_trunc: bool,
    pub flow: Option<*const core::Flow>,
}

impl DCERPCState {
    pub fn new() -> DCERPCState {
        return DCERPCState {
            header: None,
            bind: None,
            bindack: None,
            transactions: Vec::new(),
            buffer_ts: Vec::new(),
            buffer_tc: Vec::new(),
            pad: 0,
            padleft: 0,
            bytes_consumed: 0,
            tx_id: 0,
            query_completed: false,
            data_needed_for_dir: core::STREAM_TOSERVER,
            prev_dir: core::STREAM_TOSERVER,
            prev_tx_call_id: 0,
            clear_bind_cache: false,
            ts_gap: false,
            tc_gap: false,
            ts_ssn_gap: false,
            tc_ssn_gap: false,
            ts_ssn_trunc: false,
            tc_ssn_trunc: false,
            flow: None,
        };
    }

    fn create_tx(&mut self, call_id: u32) -> DCERPCTransaction {
        let mut tx = DCERPCTransaction::new();
        let endianness = self.get_hdr_drep_0() & 0x10;
        tx.id = self.tx_id;
        tx.call_id = call_id;
        tx.endianness = endianness;
        self.tx_id += 1;
        tx.req_done = self.ts_ssn_trunc;
        tx.resp_done = self.tc_ssn_trunc;
        tx
    }

    pub fn free_tx(&mut self, tx_id: u64) {
        SCLogDebug!("Freeing TX with ID {} TX.ID {}", tx_id, tx_id+1);
        let len = self.transactions.len();
        let mut found = false;
        let mut index = 0;
        for i in 0..len {
            let tx = &self.transactions[i];
            if tx.id as u64 == tx_id { //+ 1 {
                found = true;
                index = i;
                SCLogDebug!("tx {} progress {}/{}", tx.id, tx.req_done, tx.resp_done);
                break;
            }
        }
        if found {
            SCLogDebug!("freeing TX with ID {} TX.ID {} at index {} left: {} max id: {}",
                            tx_id, tx_id+1, index, self.transactions.len(), self.tx_id);
            self.transactions.remove(index);
        }
    }

    fn get_hdr_drep_0(&self) -> u8 {
        if let Some(ref hdr) = &self.header {
            return hdr.packed_drep[0];
        }
        0
    }

    fn get_endianness(&self) -> Endianness {
        let drep_0 = self.get_hdr_drep_0();
        if drep_0 & 0x10 == 0 {
            return Endianness::Big;
        }
        Endianness::Little
    }

    fn get_hdr_fraglen(&self) -> Option<u16> {
        debug_validate_bug_on!(self.header.is_none());
        if let Some(ref hdr) = self.header {
            return Some(hdr.frag_length);
        }
        // Shouldn't happen
        None
    }

    fn get_hdr_pfcflags(&self) -> Option<u8> {
        debug_validate_bug_on!(self.header.is_none());
        if let Some(ref hdr) = self.header {
            return Some(hdr.pfc_flags);
        }
        // Shouldn't happen
        None
    }

    pub fn get_hdr_type(&self) -> Option<u8> {
        debug_validate_bug_on!(self.header.is_none());
        if let Some(ref hdr) = self.header {
            return Some(hdr.hdrtype);
        }
        // Shouldn't happen
        None
    }

    pub fn get_hdr_rpc_vers(&self) -> Option<u8> {
        debug_validate_bug_on!(self.header.is_none());
        if let Some(ref hdr) = self.header {
            return Some(hdr.rpc_vers);
        }
        // Shouldn't happen
        None
    }

    pub fn get_hdr_call_id(&self) -> Option<u32> {
        debug_validate_bug_on!(self.header.is_none());
        if let Some(ref hdr) = self.header {
            return Some(hdr.call_id);
        }
        // Shouldn't happen
        None
    }

    pub fn handle_gap_ts(&mut self) -> u8 {
        if self.buffer_ts.len() > 0 {
            self.buffer_ts.clear();
        }
        return 0;
    }

    pub fn handle_gap_tc(&mut self) -> u8 {
        if self.buffer_tc.len() > 0 {
            self.buffer_tc.clear();
        }
        return 0;
    }

    pub fn clean_buffer(&mut self, direction: u8) {
        match direction {
            core::STREAM_TOSERVER => {
                self.buffer_ts.clear();
                self.ts_gap = false;
            }
            _ => {
                self.buffer_tc.clear();
                self.tc_gap = false;
            }
        }
        self.bytes_consumed = 0;
    }

    pub fn extend_buffer(&mut self, buffer: &[u8], direction: u8) {
        match direction {
            core::STREAM_TOSERVER => {
                self.buffer_ts.extend_from_slice(buffer);
            }
            _ => {
                self.buffer_tc.extend_from_slice(buffer);
            }
        }
        self.data_needed_for_dir = direction;
    }

    pub fn reset_direction(&mut self, direction: u8) {
        if direction == core::STREAM_TOSERVER {
            self.data_needed_for_dir = core::STREAM_TOCLIENT;
        } else {
            self.data_needed_for_dir = core::STREAM_TOSERVER;
        }
    }

    /// Get transaction as per the given transaction ID. Transaction ID with
    /// which the lookup is supposed to be done as per the calls from AppLayer
    /// parser in C. This requires an internal transaction ID to be maintained.
    ///
    /// Arguments:
    /// * `tx_id`:
    ///           type: unsigned 32 bit integer
    ///    description: internal transaction ID to track transactions
    ///
    /// Return value:
    /// Option mutable reference to DCERPCTransaction
    pub fn get_tx(&mut self, tx_id: u64) -> Option<&mut DCERPCTransaction> {
        for tx in &mut self.transactions {
            let found = tx.id == tx_id;
            if found {
                return Some(tx);
            }
        }
        None
    }

    /// Find the transaction as per call ID defined in header. If the tx is not
    /// found, create one.
    ///
    /// Arguments:
    /// * `call_id`:
    ///             type: unsigned 32 bit integer
    ///      description: call_id param derived from TCP Header
    /// * `dir`:
    ///         type: unsigned 8 bit integer
    ///  description: direction of the flow
    ///
    /// Return value:
    /// Option mutable reference to DCERPCTransaction
    pub fn get_tx_by_call_id(&mut self, call_id: u32, dir: u8) -> Option<&mut DCERPCTransaction> {
        let cmd = self.get_hdr_type().unwrap_or(0);
        for tx in &mut self.transactions {
            let found = tx.call_id == call_id;
            if found {
                match dir {
                    core::STREAM_TOSERVER => {
                        let resp_cmd = get_resp_type_for_req(cmd);
                        if resp_cmd != tx.resp_cmd {
                            continue;
                        }
                    }
                    _ => {
                        let req_cmd = get_req_type_for_resp(cmd);
                        if req_cmd != tx.req_cmd {
                            continue;
                        }
                    }
                }
                return Some(tx);
            }
        }
        None
    }

    pub fn handle_bind_cache(&mut self, call_id: u32, is_response: bool) {
        if self.clear_bind_cache == true {
            self.bind = None;
            self.bindack = None;
        }
        if self.prev_tx_call_id == call_id && is_response == true {
            self.clear_bind_cache = true;
        } else {
            self.clear_bind_cache = false;
        }
        self.prev_tx_call_id = call_id;
    }

    pub fn parse_data_gap(&mut self, direction: u8) -> AppLayerResult {
        match direction {
            core::STREAM_TOSERVER => {
                self.ts_gap = true;
                self.ts_ssn_gap = true;
            },
            _ => {
                self.tc_gap = true;
                self.tc_ssn_gap = true;
            },
        }
        AppLayerResult::ok()
    }

    pub fn post_gap_housekeeping(&mut self, dir: u8) {
        SCLogDebug!("ts ssn gap: {:?}, tc ssn gap: {:?}, dir: {:?}", self.ts_ssn_gap, self.tc_ssn_gap, dir);
        if self.ts_ssn_gap && dir == core::STREAM_TOSERVER {
            for tx in &mut self.transactions {
                if tx.id >= self.tx_id {
                    SCLogDebug!("post_gap_housekeeping: done");
                    break;
                }
                if tx.req_done == false {
                    tx.req_lost = true;
                }
                tx.req_done = true;
                if let Some(flow) = self.flow {
                    sc_app_layer_parser_trigger_raw_stream_reassembly(flow, dir.into());
                }
            }
        } else if self.tc_ssn_gap && dir == core::STREAM_TOCLIENT {
            for tx in &mut self.transactions {
                if tx.id >= self.tx_id {
                    SCLogDebug!("post_gap_housekeeping: done");
                    break;
                }
                if tx.req_done == false {
                    tx.req_lost = true;
                }
                if tx.resp_done == false {
                    tx.resp_lost = true;
                }
                tx.req_done = true;
                tx.resp_done = true;
                if let Some(flow) = self.flow {
                    sc_app_layer_parser_trigger_raw_stream_reassembly(flow, dir.into());
                }
            }
        }
    }

    pub fn search_dcerpc_record<'a>(&mut self, i: &'a[u8]) -> nom::IResult<&'a[u8], &'a[u8]> {
        let mut d = i;
        while d.len() >= 2 {
            if d[0] == 0x05 && d[1] == 0x00 {
                return Ok((&d[2..], d));
            }
            d = &d[1..];
        }
        Err(nom::Err::Incomplete(nom::Needed::Size(2 as usize - d.len())))
    }

    /// Makes a call to the nom parser for parsing DCERPC Header.
    ///
    /// Arguments:
    /// * `input`:
    ///           type: u8 vector slice.
    ///    description: bytes from the beginning of the buffer.
    ///
    /// Return value:
    /// * Success: Number of bytes successfully parsed.
    /// * Failure: -1 in case of Incomplete data or Eof.
    ///            -2 in case of Error while parsing.
    pub fn process_header(&mut self, input: &[u8]) -> i32 {
        match parser::parse_dcerpc_header(input) {
            Ok((leftover_bytes, header)) => {
                if header.rpc_vers != 5
                    || (header.rpc_vers_minor != 0 && header.rpc_vers_minor != 1)
                {
                    SCLogDebug!(
                        "DCERPC Header did not validate. Major version: {:?} Minor version: {:?}",
                        header.rpc_vers,
                        header.rpc_vers_minor
                    );
                    return -1;
                }
                self.header = Some(header);
                (input.len() - leftover_bytes.len()) as i32
            }
            Err(nom::Err::Incomplete(_)) => {
                // Insufficient data.
                SCLogDebug!("Insufficient data while parsing DCERPC header");
                -1
            }
            Err(nom::Err::Error(([], ErrorKind::Eof))) => {
                SCLogDebug!("EoF reached while parsing DCERPC header");
                -1
            }
            Err(_) => {
                // Error, probably malformed data.
                SCLogDebug!("An error occured while parsing DCERPC header");
                -2
            }
        }
    }

    pub fn handle_bindctxitem(&mut self, input: &[u8], uuid_internal_id: u16) -> i32 {
        let endianness = self.get_endianness();
        match parser::parse_bindctx_item(input, endianness) {
            Ok((leftover_bytes, ctxitem)) => {
                let mut uuidentry = DCERPCUuidEntry::new();
                uuidentry.uuid = ctxitem.uuid;
                uuidentry.internal_id = uuid_internal_id;
                uuidentry.ctxid = ctxitem.ctxid;
                uuidentry.version = ctxitem.version;
                uuidentry.versionminor = ctxitem.versionminor;
                let pfcflags = self.get_hdr_pfcflags().unwrap_or(0);
                // Store the first frag flag in the uuid as pfc_flags will
                // be overwritten by new packets
                if pfcflags & PFC_FIRST_FRAG > 0 {
                    uuidentry.flags |= DCERPC_UUID_ENTRY_FLAG_FF;
                }
                if let Some(ref mut bind) = self.bind {
                    SCLogDebug!("DCERPC BIND CtxItem: Pushing uuid: {:?}", uuidentry);
                    bind.uuid_list.push(uuidentry);
                }
                (input.len() - leftover_bytes.len()) as i32
            }
            Err(nom::Err::Incomplete(_)) => {
                // Insufficient data.
                SCLogDebug!("Insufficient data while parsing DCERPC BIND CTXItem");
                -1
            }
            Err(_) => {
                // Error, probably malformed data.
                SCLogDebug!("An error occurred while parsing DCERPC BIND CTXItem");
                -1
            }
        }
    }

    pub fn process_bind_pdu(&mut self, input: &[u8]) -> i32 {
        let mut retval = 0;
        let mut idx = 12; // Bytes consumed if parser returns OK would be 12
        match parser::parse_dcerpc_bind(input) {
            Ok((leftover_bytes, header)) => {
                let numctxitems = header.numctxitems;
                self.bind = Some(header);
                for i in 0..numctxitems {
                    retval = self.handle_bindctxitem(&input[idx as usize..], i as u16);
                    if retval == -1 {
                        return -1;
                    }
                    idx = retval + idx;
                }
                let call_id = self.get_hdr_call_id().unwrap_or(0);
                let mut tx = self.create_tx(call_id);
                tx.req_cmd = self.get_hdr_type().unwrap_or(0);
                tx.req_done = true;
                if let Some(flow) = self.flow {
                    sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
                }
                tx.frag_cnt_ts = 1;
                self.transactions.push(tx);
                // Bytes parsed with `parse_dcerpc_bind` + (bytes parsed per bindctxitem [44] * number
                // of bindctxitems)
                (input.len() - leftover_bytes.len()) as i32 + retval * numctxitems as i32
            }
            Err(nom::Err::Incomplete(_)) => {
                // Insufficient data.
                SCLogDebug!("Insufficient data while parsing DCERPC BIND header");
                -1
            }
            Err(_) => {
                // Error, probably malformed data.
                SCLogDebug!("An error occurred while parsing DCERPC BIND header");
                -1
            }
        }
    }

    pub fn process_bindack_pdu(&mut self, input: &[u8]) -> i32 {
        match parser::parse_dcerpc_bindack(input) {
            Ok((leftover_bytes, mut back)) => {
                if let Some(ref mut bind) = self.bind {
                    let mut uuid_internal_id = 0;
                    for r in back.ctxitems.iter() {
                        for mut uuid in bind.uuid_list.iter_mut() {
                            if uuid.internal_id == uuid_internal_id {
                                uuid.result = r.ack_result;
                                if uuid.result != 0 {
                                    break;
                                }
                                back.accepted_uuid_list.push(uuid.clone());
                                SCLogDebug!("DCERPC BINDACK accepted UUID: {:?}", uuid);
                            }
                        }
                        uuid_internal_id += 1;
                    }
                    self.bindack = Some(back);
                }
                (input.len() - leftover_bytes.len()) as i32
            }
            Err(nom::Err::Incomplete(_)) => {
                // Insufficient data.
                SCLogDebug!("Insufficient data while parsing DCERPC BINDACK");
                -1
            }
            Err(_) => {
                // Error, probably malformed data.
                SCLogDebug!("An error occurred while parsing DCERPC BINDACK");
                -1
            }
        }
    }

    pub fn handle_stub_data(&mut self, input: &[u8], input_len: u16, dir: u8) -> u16 {
        let retval;
        let hdrpfcflags = self.get_hdr_pfcflags().unwrap_or(0);
        let padleft = self.padleft;
        let call_id = self.get_hdr_call_id().unwrap_or(0);
        let hdrtype = self.get_hdr_type();
        let tx;
        if let Some(transaction) = self.get_tx_by_call_id(call_id, dir) {
            tx = transaction;
        } else {
            SCLogDebug!("No transaction found matching the call ID: {:?}", call_id);
            return 0;
        }

        // Update the stub params based on the packet type
        match hdrtype {
            Some(x) => match x {
                DCERPC_TYPE_REQUEST => {
                    retval = evaluate_stub_params(
                        input,
                        input_len,
                        hdrpfcflags,
                        padleft,
                        &mut tx.stub_data_buffer_ts,
                        &mut tx.stub_data_buffer_reset_ts,
                    );
                    tx.req_done = true;
                    tx.frag_cnt_ts = 1;
                    if let Some(flow) = self.flow {
                        sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
                    }
                }
                DCERPC_TYPE_RESPONSE => {
                    retval = evaluate_stub_params(
                        input,
                        input_len,
                        hdrpfcflags,
                        padleft,
                        &mut tx.stub_data_buffer_tc,
                        &mut tx.stub_data_buffer_reset_tc,
                    );
                    tx.resp_done = true;
                    tx.frag_cnt_tc = 1;
                    if let Some(flow) = self.flow {
                        sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
                    }
                }
                _ => {
                    SCLogDebug!("Unrecognized packet type");
                    return 0;
                }
            },
            None => {
                return 0;
            }
        }
        // Update the remaining fragment length
        self.padleft -= retval;

        retval
    }

    /// Handles stub data for both request and response.
    ///
    /// Arguments:
    /// * `input`:
    ///           type: u8 vector slice.
    ///    description: bytes left *after* parsing header.
    /// * `bytes_consumed`:
    ///           type: 16 bit unsigned integer.
    ///    description: bytes consumed *after* parsing header.
    /// * `dir`:
    ///           type: 8 bit unsigned integer.
    ///    description: direction whose stub is supposed to be handled.
    ///
    /// Return value:
    /// * Success: Number of bytes successfully parsed.
    /// * Failure: -1 in case fragment length defined by header mismatches the data.
    pub fn handle_common_stub(&mut self, input: &[u8], bytes_consumed: u16, dir: u8) -> i32 {
        let fraglen = self.get_hdr_fraglen().unwrap_or(0);
        if fraglen < bytes_consumed as u16 + DCERPC_HDR_LEN {
            return -1;
        }
        self.padleft = fraglen - DCERPC_HDR_LEN - bytes_consumed;
        let mut input_left = input.len() as u16 - bytes_consumed;
        let mut parsed = bytes_consumed as i32;
        while input_left > 0 && parsed < fraglen as i32 {
            let retval = self.handle_stub_data(&input[parsed as usize..], input_left, dir);
            if retval > 0 && retval <= input_left {
                parsed += retval as i32;
                input_left -= retval;
            } else if input_left > 0 {
                SCLogDebug!(
                    "Error parsing DCERPC {} stub data",
                    if dir == core::STREAM_TOSERVER {
                        "request"
                    } else {
                        "response"
                    }
                );
                parsed -= input_left as i32;
                input_left = 0;
            }
        }
        parsed
    }

    pub fn process_request_pdu(&mut self, input: &[u8]) -> i32 {
        let endianness = self.get_endianness();
        match parser::parse_dcerpc_request(input, endianness) {
            Ok((leftover_input, request)) => {
                let call_id = self.get_hdr_call_id().unwrap_or(0);
                let hdr_type = self.get_hdr_type().unwrap_or(0);
                let mut transaction = self.get_tx_by_call_id(call_id, core::STREAM_TOSERVER);
                match transaction {
                    Some(ref mut tx) => {
                        tx.req_cmd = hdr_type;
                        tx.ctxid = request.ctxid;
                        tx.opnum = request.opnum;
                        tx.first_request_seen = request.first_request_seen;
                    }
                    None => {
                        let mut tx = self.create_tx(call_id);
                        tx.req_cmd = hdr_type;
                        tx.ctxid = request.ctxid;
                        tx.opnum = request.opnum;
                        tx.first_request_seen = request.first_request_seen;
                        self.transactions.push(tx);
                    }
                }
                let parsed = self.handle_common_stub(
                    &input,
                    (input.len() - leftover_input.len()) as u16,
                    core::STREAM_TOSERVER,
                );
                parsed
            }
            Err(nom::Err::Incomplete(_)) => {
                // Insufficient data.
                SCLogDebug!("Insufficient data while parsing DCERPC REQUEST");
                -1
            }
            Err(_) => {
                // Error, probably malformed data.
                SCLogDebug!("An error occurred while parsing DCERPC REQUEST");
                -1
            }
        }
    }

    pub fn handle_input_data(&mut self, input: &[u8], direction: u8) -> AppLayerResult {
        let mut parsed;
        let retval;
        let mut cur_i = input;
        let input_len = cur_i.len();
        let mut v: Vec<u8>;
        // Set any query's completion status to false in the beginning
        self.query_completed = false;

        // Skip the record since this means that its in the middle of a known length record
        if (self.ts_gap && direction == core::STREAM_TOSERVER) || (self.tc_gap && direction == core::STREAM_TOCLIENT) {
            SCLogDebug!("Trying to catch up after GAP (input {})", cur_i.len());
            match self.search_dcerpc_record(cur_i) {
                Ok((_, pg)) => {
                    SCLogDebug!("DCERPC record found");
                    let offset = cur_i.len() - pg.len();
                    cur_i = &cur_i[offset..];
                    match direction {
                        core::STREAM_TOSERVER => {
                            self.ts_gap = false;
                        },
                        _ => {
                            self.tc_gap = false;
                        }
                    }
                },
                _ => {
                    let mut consumed = cur_i.len();
                    // At least 2 bytes are required to know if a new record is beginning
                    if consumed < 2 {
                        consumed = 0;
                    } else {
                        consumed = consumed - 1;
                    }
                    SCLogDebug!("DCERPC record NOT found");
                    return AppLayerResult::incomplete(consumed as u32, 2);
                },
            }
        }

        // Overwrite the dcerpc_state data in case of multiple complete queries in the
        // same direction
        if self.prev_dir == direction {
            self.data_needed_for_dir = direction;
        }

        let buffer = match direction {
            core::STREAM_TOSERVER => {
                if self.buffer_ts.len() + input_len > 1024 * 1024 {
                    SCLogDebug!("DCERPC TOSERVER stream: Buffer Overflow");
                    return AppLayerResult::err();
                }
                v = self.buffer_ts.split_off(0);
                v.extend_from_slice(cur_i);
                v.as_slice()
            }
            _ => {
                if self.buffer_tc.len() + input_len > 1024 * 1024 {
                    SCLogDebug!("DCERPC TOCLIENT stream: Buffer Overflow");
                    return AppLayerResult::err();
                }
                v = self.buffer_tc.split_off(0);
                v.extend_from_slice(cur_i);
                v.as_slice()
            }
        };

        if self.data_needed_for_dir != direction && buffer.len() != 0 {
            return AppLayerResult::err();
        }

        // Set data_needed_for_dir in the same direction in case there is an issue with upcoming parsing
        self.data_needed_for_dir = direction;

        // Check if header data was complete. In case of EoF or incomplete data, wait for more
        // data else return error
        if self.bytes_consumed < DCERPC_HDR_LEN && input_len > 0 {
            parsed = self.process_header(&buffer);
            if parsed == -1 {
                self.extend_buffer(buffer, direction);
                return AppLayerResult::ok();
            }
            if parsed == -2 {
                return AppLayerResult::err();
            }
            self.bytes_consumed += parsed as u16;
        }

        let fraglen = self.get_hdr_fraglen().unwrap_or(0);

        if (buffer.len() as u16) < fraglen {
            SCLogDebug!("Possibly fragmented data, waiting for more..");
            self.extend_buffer(buffer, direction);
            return AppLayerResult::ok();
        } else {
            self.query_completed = true;
        }
        parsed = self.bytes_consumed as i32;

        let current_call_id = self.get_hdr_call_id().unwrap_or(0);

        match self.get_hdr_type() {
            Some(x) => match x {
                DCERPC_TYPE_BIND | DCERPC_TYPE_ALTER_CONTEXT => {
                    retval = self.process_bind_pdu(&buffer[parsed as usize..]);
                    if retval == -1 {
                        return AppLayerResult::err();
                    }
                    self.handle_bind_cache(current_call_id, false);
                }
                DCERPC_TYPE_BINDACK | DCERPC_TYPE_ALTER_CONTEXT_RESP => {
                    retval = self.process_bindack_pdu(&buffer[parsed as usize..]);
                    if retval == -1 {
                        return AppLayerResult::err();
                    }
                    let tx = if let Some(tx) = self.get_tx_by_call_id(current_call_id, core::STREAM_TOCLIENT) {
                        tx.resp_cmd = x;
                        tx
                    } else {
                        let mut tx = self.create_tx(current_call_id);
                        tx.resp_cmd = x;
                        self.transactions.push(tx);
                        self.transactions.last_mut().unwrap()
                    };
                    tx.resp_done = true;
                    tx.frag_cnt_tc = 1;
                    if let Some(flow) = self.flow {
                        sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
                    }
                    self.handle_bind_cache(current_call_id, false);
                }
                DCERPC_TYPE_REQUEST => {
                    retval = self.process_request_pdu(&buffer[parsed as usize..]);
                    if retval < 0 {
                        return AppLayerResult::err();
                    }
                    // In case the response came first, the transaction would complete later when
                    // the corresponding request also comes through
                    self.handle_bind_cache(current_call_id, false);
                }
                DCERPC_TYPE_RESPONSE => {
                    let transaction = self.get_tx_by_call_id(current_call_id, core::STREAM_TOCLIENT);
                    match transaction {
                        Some(tx) => {
                            tx.resp_cmd = x;
                        }
                        None => {
                            let mut tx = self.create_tx(current_call_id);
                            tx.resp_cmd = x;
                            self.transactions.push(tx);
                        }
                    };
                    retval = self.handle_common_stub(
                        &buffer[parsed as usize..],
                        0,
                        core::STREAM_TOCLIENT,
                    );
                    if retval < 0 {
                        return AppLayerResult::err();
                    }
                    self.handle_bind_cache(current_call_id, true);
                }
                _ => {
                    SCLogDebug!("Unrecognized packet type: {:?}", x);
                    self.clean_buffer(direction);
                    return AppLayerResult::err();
                }
            },
            None => {
                return AppLayerResult::err();
            }
        }
        self.bytes_consumed += retval as u16;

        // If the query has been completed, clean the buffer and reset the direction
        if self.query_completed == true {
            self.clean_buffer(direction);
            self.reset_direction(direction);
        }
        self.post_gap_housekeeping(direction);
        self.prev_dir = direction;
        return AppLayerResult::ok();
    }
}

fn evaluate_stub_params(
    input: &[u8], input_len: u16, hdrflags: u8, lenleft: u16,
    stub_data_buffer: &mut Vec<u8>,stub_data_buffer_reset: &mut bool,
) -> u16 {
    let stub_len: u16;
    let fragtype = hdrflags & (PFC_FIRST_FRAG | PFC_LAST_FRAG);
    stub_len = cmp::min(lenleft, input_len);
    if stub_len == 0 {
        return 0;
    }
    if stub_len == lenleft && (fragtype == 0 || (fragtype & PFC_LAST_FRAG > 0)) {
        *stub_data_buffer_reset = true;
    }

    let input_slice = &input[..stub_len as usize];
    stub_data_buffer.extend_from_slice(&input_slice);

    stub_len
}

#[no_mangle]
pub extern "C" fn rs_parse_dcerpc_request_gap(
    state: &mut DCERPCState,
    _input_len: u32,
) -> AppLayerResult {
    state.parse_data_gap(core::STREAM_TOSERVER)
}

#[no_mangle]
pub extern "C" fn rs_parse_dcerpc_response_gap(
    state: &mut DCERPCState,
    _input_len: u32,
) -> AppLayerResult {
    state.parse_data_gap(core::STREAM_TOCLIENT)
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_parse_request(
    flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
    input: *const u8, input_len: u32, _data: *mut std::os::raw::c_void, flags: u8,
) -> AppLayerResult {
    SCLogDebug!("Handling request: input {:p} input_len {} flags {:x} EOF {}",
            input, input_len, flags, flags & core::STREAM_EOF != 0);
    if flags & core::STREAM_EOF != 0 && input_len == 0 {
        return AppLayerResult::ok();
    }
    /* START with MIDSTREAM set: record might be starting the middle. */
    if flags & (core::STREAM_START|core::STREAM_MIDSTREAM) == (core::STREAM_START|core::STREAM_MIDSTREAM) {
        state.ts_gap = true;
    }
    if input_len > 0 && input != std::ptr::null_mut() {
        let buf = build_slice!(input, input_len as usize);
        state.flow = Some(flow);
        return state.handle_input_data(buf, core::STREAM_TOSERVER);
    }
    AppLayerResult::err()
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_parse_response(
    flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
    input: *const u8, input_len: u32, _data: *mut std::os::raw::c_void, flags: u8,
) -> AppLayerResult {
    if flags & core::STREAM_EOF != 0 && input_len == 0 {
        return AppLayerResult::ok();
    }
    /* START with MIDSTREAM set: record might be starting the middle. */
    if flags & (core::STREAM_START|core::STREAM_MIDSTREAM) == (core::STREAM_START|core::STREAM_MIDSTREAM) {
        state.tc_gap = true;
    }
    if input_len > 0 {
        if input != std::ptr::null_mut() {
            let buf = build_slice!(input, input_len as usize);
            state.flow = Some(flow);
            return state.handle_input_data(buf, core::STREAM_TOCLIENT);
        }
    }
    AppLayerResult::err()
}

#[no_mangle]
pub unsafe extern "C" fn rs_dcerpc_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: core::AppProto) -> *mut std::os::raw::c_void {
    let state = DCERPCState::new();
    let boxed = Box::new(state);
    transmute(boxed)
}

#[no_mangle]
pub unsafe extern "C" fn rs_dcerpc_state_free(state: *mut std::os::raw::c_void) {
    let _drop: Box<DCERPCState> = transmute(state);
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_state_transaction_free(state: *mut std::os::raw::c_void, tx_id: u64) {
    let dce_state = cast_pointer!(state, DCERPCState);
    SCLogDebug!("freeing tx {}", tx_id as u64);
    dce_state.free_tx(tx_id);
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_state_trunc(state: *mut std::os::raw::c_void, direction: u8) {
    let dce_state = cast_pointer!(state, DCERPCState);
    if direction & core::STREAM_TOSERVER != 0 {
        dce_state.ts_ssn_trunc = true;
        for tx in &mut dce_state.transactions {
            tx.req_done = true;
            if let Some(flow) = dce_state.flow {
                sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
            }
        }
        SCLogDebug!("dce_state.ts_ssn_trunc = true; txs {}", dce_state.transactions.len());
    } else if direction & core::STREAM_TOCLIENT != 0 {
        dce_state.tc_ssn_trunc = true;
        for tx in &mut dce_state.transactions {
            tx.resp_done = true;
            if let Some(flow) = dce_state.flow {
                sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
            }
        }
        SCLogDebug!("dce_state.tc_ssn_trunc = true; txs {}", dce_state.transactions.len());
    }
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_get_tx_detect_state(
    vtx: *mut std::os::raw::c_void,
) -> *mut core::DetectEngineState {
    let dce_tx = cast_pointer!(vtx, DCERPCTransaction);
    match dce_tx.de_state {
        Some(ds) => ds,
        None => std::ptr::null_mut(),
    }
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_set_tx_detect_state(
    vtx: *mut std::os::raw::c_void, de_state: *mut core::DetectEngineState,
) -> u8 {
    let dce_tx = cast_pointer!(vtx, DCERPCTransaction);
    dce_tx.de_state = Some(de_state);
    0
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_get_tx(
    vtx: *mut std::os::raw::c_void, tx_id: u64,
) -> *mut DCERPCTransaction {
    let dce_state = cast_pointer!(vtx, DCERPCState);
    match dce_state.get_tx(tx_id) {
        Some(tx) => tx,
        None => std::ptr::null_mut(),
    }
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_get_tx_cnt(vtx: *mut std::os::raw::c_void) -> u64 {
    let dce_state = cast_pointer!(vtx, DCERPCState);
    dce_state.tx_id
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_get_alstate_progress(tx: &mut DCERPCTransaction, direction: u8) -> u8 {
    if direction == core::STREAM_TOSERVER && tx.req_done {
        SCLogDebug!("tx {} TOSERVER progress 1 => {:?}", tx.call_id, tx);
        return 1;
    } else if direction == core::STREAM_TOCLIENT && tx.resp_done {
        SCLogDebug!("tx {} TOCLIENT progress 1 => {:?}", tx.call_id, tx);
        return 1;
    }
    SCLogDebug!("tx {} direction {} progress 0", tx.call_id, direction);
    return 0;
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_get_tx_data(
    tx: *mut std::os::raw::c_void)
    -> *mut AppLayerTxData
{
    let tx = cast_pointer!(tx, DCERPCTransaction);
    return &mut tx.tx_data;
}

#[no_mangle]
pub unsafe extern "C" fn rs_dcerpc_get_stub_data(
    tx: &mut DCERPCTransaction, buf: *mut *const u8, len: *mut u32, endianness: *mut u8, dir: u8,
) {
    match dir {
        core::STREAM_TOSERVER => {
            *len = tx.stub_data_buffer_ts.len() as u32;
            *buf = tx.stub_data_buffer_ts.as_ptr();
            SCLogDebug!("DCERPC Request stub buffer: Setting buffer to: {:?}", *buf);
        }
        _ => {
            *len = tx.stub_data_buffer_tc.len() as u32;
            *buf = tx.stub_data_buffer_tc.as_ptr();
            SCLogDebug!("DCERPC Response stub buffer: Setting buffer to: {:?}", *buf);
        }
    }
    *endianness = tx.get_endianness();
}

/// Probe input to see if it looks like DCERPC.
fn probe(input: &[u8]) -> (bool, bool) {
    match parser::parse_dcerpc_header(input) {
        Ok((_, hdr)) => {
            let is_request = hdr.hdrtype == 0x00;
            let is_dcerpc = hdr.rpc_vers == 0x05 && hdr.rpc_vers_minor == 0x00;
            return (is_dcerpc, is_request);
        },
        Err(_) => (false, false),
    }
}

#[no_mangle]
pub extern "C" fn rs_dcerpc_probe_tcp(direction: u8, input: *const u8,
                                      len: u32, rdir: *mut u8) -> i32
{
    SCLogDebug!("Probing packet for DCERPC");
    if len == 0 {
        return core::ALPROTO_UNKNOWN;
    }
    let slice: &[u8] = unsafe {
        std::slice::from_raw_parts(input as *mut u8, len as usize)
    };
    //is_incomplete is checked by caller
    let (is_dcerpc, is_request, ) = probe(slice);
    if is_dcerpc {
        let dir = if is_request {
            core::STREAM_TOSERVER
        } else {
            core::STREAM_TOCLIENT
        };
        if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
            unsafe { *rdir = dir };
        }
        return 1;
    }
    return 0;

}

#[cfg(test)]
mod tests {
    use crate::applayer::AppLayerResult;
    use crate::core;
    use crate::dcerpc::dcerpc::DCERPCState;
    use std::cmp;

    #[test]
    fn test_process_header() {
        let request: &[u8] = &[
            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(16, dcerpc_state.process_header(request));
    }

    #[test]
    fn test_process_bind_pdu() {
        let header: &[u8] = &[
            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00,
        ];
        let bind: &[u8] = &[
            0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f, 0xbf, 0x85,
            0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0x2c, 0x75, 0xce, 0x7e, 0x82, 0x3b, 0x06, 0xac, 0x1b, 0xf0,
            0xf5, 0xb7, 0xa7, 0xf7, 0x28, 0xaf, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xe3, 0xb2, 0x10, 0xd1, 0xd0, 0x0c, 0xcc, 0x3d,
            0x2f, 0x80, 0x20, 0x7c, 0xef, 0xe7, 0x09, 0xe0, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xde, 0x85, 0x70, 0xc4, 0x02, 0x7c,
            0x60, 0x23, 0x67, 0x0c, 0x22, 0xbf, 0x18, 0x36, 0x79, 0x17, 0x01, 0x00, 0x02, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x41, 0x65, 0x29, 0x51,
            0xaa, 0xe7, 0x7b, 0xa8, 0xf2, 0x37, 0x0b, 0xd0, 0x3f, 0xb3, 0x36, 0xed, 0x05, 0x00,
            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x14, 0x96,
            0x80, 0x01, 0x2e, 0x78, 0xfb, 0x5d, 0xb4, 0x3c, 0x14, 0xb3, 0x3d, 0xaa, 0x02, 0xfb,
            0x06, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00,
            0x3b, 0x04, 0x68, 0x3e, 0x63, 0xfe, 0x9f, 0xd8, 0x64, 0x55, 0xcd, 0xe7, 0x39, 0xaf,
            0x98, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00,
            0x01, 0x00, 0x16, 0x7a, 0x4f, 0x1b, 0xdb, 0x25, 0x92, 0x55, 0xdd, 0xae, 0x9e, 0x5b,
            0x3e, 0x93, 0x66, 0x93, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x08, 0x00, 0x01, 0x00, 0xe8, 0xa4, 0x8a, 0xcf, 0x95, 0x6c, 0xc7, 0x8f, 0x14, 0xcc,
            0x56, 0xfc, 0x7b, 0x5f, 0x4f, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xd8, 0xda, 0xfb, 0xbc, 0xa2, 0x55, 0x6f, 0x5d,
            0xc0, 0x2d, 0x88, 0x6f, 0x00, 0x17, 0x52, 0x8d, 0x06, 0x00, 0x03, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x3f, 0x17, 0x55, 0x0c, 0xf4, 0x23,
            0x3c, 0xca, 0xe6, 0xa0, 0xaa, 0xcc, 0xb5, 0xe3, 0xf9, 0xce, 0x04, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x6a, 0x28, 0x19, 0x39,
            0x0c, 0xb1, 0xd0, 0x11, 0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5, 0x00, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0xc9, 0x9f,
            0x3e, 0x6e, 0x82, 0x0a, 0x2b, 0x28, 0x37, 0x78, 0xe1, 0x13, 0x70, 0x05, 0x38, 0x4d,
            0x01, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x00,
            0x11, 0xaa, 0x4b, 0x15, 0xdf, 0xa6, 0x86, 0x3f, 0xfb, 0xe0, 0x09, 0xb7, 0xf8, 0x56,
            0xd2, 0x3f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00,
            0x01, 0x00, 0xee, 0x99, 0xc4, 0x25, 0x11, 0xe4, 0x95, 0x62, 0x29, 0xfa, 0xfd, 0x26,
            0x57, 0x02, 0xf1, 0xce, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x0f, 0x00, 0x01, 0x00, 0xba, 0x81, 0x9e, 0x1a, 0xdf, 0x2b, 0xba, 0xe4, 0xd3, 0x17,
            0x41, 0x60, 0x6d, 0x2d, 0x9e, 0x28, 0x03, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0xa0, 0x24, 0x03, 0x9a, 0xa9, 0x99, 0xfb, 0xbe,
            0x49, 0x11, 0xad, 0x77, 0x30, 0xaa, 0xbc, 0xb6, 0x02, 0x00, 0x03, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x32, 0x04, 0x7e, 0xae, 0xec, 0x28,
            0xd1, 0x55, 0x83, 0x4e, 0xc3, 0x47, 0x5d, 0x1d, 0xc6, 0x65, 0x02, 0x00, 0x03, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0xc6, 0xa4, 0x81, 0x48,
            0x66, 0x2a, 0x74, 0x7d, 0x56, 0x6e, 0xc5, 0x1d, 0x19, 0xf2, 0xb5, 0xb6, 0x03, 0x00,
            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0xcb, 0xae,
            0xb3, 0xc0, 0x0c, 0xf4, 0xa4, 0x5e, 0x91, 0x72, 0xdd, 0x53, 0x24, 0x70, 0x89, 0x02,
            0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00,
            0xb8, 0xd0, 0xa0, 0x1a, 0x5e, 0x7a, 0x2d, 0xfe, 0x35, 0xc6, 0x7d, 0x08, 0x0d, 0x33,
            0x73, 0x18, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00,
            0x01, 0x00, 0x21, 0xd3, 0xaa, 0x09, 0x03, 0xa7, 0x0b, 0xc2, 0x06, 0x45, 0xd9, 0x6c,
            0x75, 0xc2, 0x15, 0xa8, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x16, 0x00, 0x01, 0x00, 0xe1, 0xbd, 0x59, 0xfc, 0xbc, 0xa9, 0x95, 0xc2, 0x68, 0x79,
            0xf3, 0x75, 0xe0, 0xae, 0x6c, 0xe5, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x06, 0x52, 0xb4, 0x71, 0x70, 0x15, 0x4e, 0xf5,
            0x7f, 0x08, 0x86, 0x14, 0xe6, 0x17, 0xd5, 0x97, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(16, dcerpc_state.process_header(header));
        assert_eq!(1068, dcerpc_state.process_bind_pdu(bind));
    }

    #[test]
    fn test_handle_bindctxitem() {
        let header: &[u8] = &[
            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00,
        ];
        let bind: &[u8] = &[
            0x00, 0x00, 0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f,
            0xbf, 0x85, 0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(16, dcerpc_state.process_header(header));
        assert_eq!(44, dcerpc_state.handle_bindctxitem(bind, 0));
    }

    #[test]
    fn test_process_bindack_pdu() {
        let bind: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f,
            0xbf, 0x85, 0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x2c, 0x75, 0xce, 0x7e, 0x82, 0x3b, 0x06, 0xac,
            0x1b, 0xf0, 0xf5, 0xb7, 0xa7, 0xf7, 0x28, 0xaf, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xe3, 0xb2, 0x10, 0xd1, 0xd0, 0x0c,
            0xcc, 0x3d, 0x2f, 0x80, 0x20, 0x7c, 0xef, 0xe7, 0x09, 0xe0, 0x04, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xde, 0x85, 0x70, 0xc4,
            0x02, 0x7c, 0x60, 0x23, 0x67, 0x0c, 0x22, 0xbf, 0x18, 0x36, 0x79, 0x17, 0x01, 0x00,
            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x41, 0x65,
            0x29, 0x51, 0xaa, 0xe7, 0x7b, 0xa8, 0xf2, 0x37, 0x0b, 0xd0, 0x3f, 0xb3, 0x36, 0xed,
            0x05, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
            0x14, 0x96, 0x80, 0x01, 0x2e, 0x78, 0xfb, 0x5d, 0xb4, 0x3c, 0x14, 0xb3, 0x3d, 0xaa,
            0x02, 0xfb, 0x06, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x3b, 0x04, 0x68, 0x3e, 0x63, 0xfe, 0x9f, 0xd8, 0x64, 0x55, 0xcd, 0xe7,
            0x39, 0xaf, 0x98, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x07, 0x00, 0x01, 0x00, 0x16, 0x7a, 0x4f, 0x1b, 0xdb, 0x25, 0x92, 0x55, 0xdd, 0xae,
            0x9e, 0x5b, 0x3e, 0x93, 0x66, 0x93, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xe8, 0xa4, 0x8a, 0xcf, 0x95, 0x6c, 0xc7, 0x8f,
            0x14, 0xcc, 0x56, 0xfc, 0x7b, 0x5f, 0x4f, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xd8, 0xda, 0xfb, 0xbc, 0xa2, 0x55,
            0x6f, 0x5d, 0xc0, 0x2d, 0x88, 0x6f, 0x00, 0x17, 0x52, 0x8d, 0x06, 0x00, 0x03, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x3f, 0x17, 0x55, 0x0c,
            0xf4, 0x23, 0x3c, 0xca, 0xe6, 0xa0, 0xaa, 0xcc, 0xb5, 0xe3, 0xf9, 0xce, 0x04, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x6a, 0x28,
            0x19, 0x39, 0x0c, 0xb1, 0xd0, 0x11, 0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5,
            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
            0xc9, 0x9f, 0x3e, 0x6e, 0x82, 0x0a, 0x2b, 0x28, 0x37, 0x78, 0xe1, 0x13, 0x70, 0x05,
            0x38, 0x4d, 0x01, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
            0x01, 0x00, 0x11, 0xaa, 0x4b, 0x15, 0xdf, 0xa6, 0x86, 0x3f, 0xfb, 0xe0, 0x09, 0xb7,
            0xf8, 0x56, 0xd2, 0x3f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x0e, 0x00, 0x01, 0x00, 0xee, 0x99, 0xc4, 0x25, 0x11, 0xe4, 0x95, 0x62, 0x29, 0xfa,
            0xfd, 0x26, 0x57, 0x02, 0xf1, 0xce, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xba, 0x81, 0x9e, 0x1a, 0xdf, 0x2b, 0xba, 0xe4,
            0xd3, 0x17, 0x41, 0x60, 0x6d, 0x2d, 0x9e, 0x28, 0x03, 0x00, 0x03, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0xa0, 0x24, 0x03, 0x9a, 0xa9, 0x99,
            0xfb, 0xbe, 0x49, 0x11, 0xad, 0x77, 0x30, 0xaa, 0xbc, 0xb6, 0x02, 0x00, 0x03, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x32, 0x04, 0x7e, 0xae,
            0xec, 0x28, 0xd1, 0x55, 0x83, 0x4e, 0xc3, 0x47, 0x5d, 0x1d, 0xc6, 0x65, 0x02, 0x00,
            0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0xc6, 0xa4,
            0x81, 0x48, 0x66, 0x2a, 0x74, 0x7d, 0x56, 0x6e, 0xc5, 0x1d, 0x19, 0xf2, 0xb5, 0xb6,
            0x03, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00,
            0xcb, 0xae, 0xb3, 0xc0, 0x0c, 0xf4, 0xa4, 0x5e, 0x91, 0x72, 0xdd, 0x53, 0x24, 0x70,
            0x89, 0x02, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
            0x01, 0x00, 0xb8, 0xd0, 0xa0, 0x1a, 0x5e, 0x7a, 0x2d, 0xfe, 0x35, 0xc6, 0x7d, 0x08,
            0x0d, 0x33, 0x73, 0x18, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x15, 0x00, 0x01, 0x00, 0x21, 0xd3, 0xaa, 0x09, 0x03, 0xa7, 0x0b, 0xc2, 0x06, 0x45,
            0xd9, 0x6c, 0x75, 0xc2, 0x15, 0xa8, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x16, 0x00, 0x01, 0x00, 0xe1, 0xbd, 0x59, 0xfc, 0xbc, 0xa9, 0x95, 0xc2,
            0x68, 0x79, 0xf3, 0x75, 0xe0, 0xae, 0x6c, 0xe5, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x06, 0x52, 0xb4, 0x71, 0x70, 0x15,
            0x4e, 0xf5, 0x7f, 0x08, 0x86, 0x14, 0xe6, 0x17, 0xd5, 0x97, 0x04, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let bindack: &[u8] = &[
            0xb8, 0x10, 0xb8, 0x10, 0xce, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x5c, 0x50, 0x49, 0x50,
            0x45, 0x5c, 0x6c, 0x73, 0x61, 0x73, 0x73, 0x00, 0xf6, 0x6e, 0x18, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(16, dcerpc_state.process_header(bind));
        assert_eq!(1068, dcerpc_state.process_bind_pdu(&bind[16..]));
        assert_eq!(604, dcerpc_state.process_bindack_pdu(bindack));
        if let Some(back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            assert_eq!(
                vec!(57, 25, 40, 106, 177, 12, 17, 208, 155, 168, 0, 192, 79, 217, 46, 245),
                back.accepted_uuid_list[0].uuid
            );
            assert_eq!(11, back.accepted_uuid_list[0].internal_id);
        }
    }

    #[test]
    pub fn test_process_request_pdu() {
        let request: &[u8] = &[
            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x45, 0x00, 0x2c, 0x00,
            0x4d, 0x00, 0x73, 0x00, 0x53, 0x00, 0x59, 0x00, 0x2a, 0x00, 0x4a, 0x00, 0x7a, 0x00,
            0x3e, 0x00, 0x58, 0x00, 0x21, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x41, 0x00, 0x4b, 0x00,
            0x4b, 0x00, 0x3c, 0x00, 0x48, 0x00, 0x24, 0x00, 0x38, 0x00, 0x54, 0x00, 0x60, 0x00,
            0x2d, 0x00, 0x29, 0x00, 0x64, 0x00, 0x5b, 0x00, 0x77, 0x00, 0x3a, 0x00, 0x4c, 0x00,
            0x24, 0x00, 0x23, 0x00, 0x66, 0x00, 0x43, 0x00, 0x68, 0x00, 0x22, 0x00, 0x55, 0x00,
            0x29, 0x00, 0x2c, 0x00, 0x4f, 0x00, 0x5a, 0x00, 0x50, 0x00, 0x61, 0x00, 0x2a, 0x00,
            0x6f, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x68, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x67, 0x00,
            0x68, 0x00, 0x68, 0x00, 0x49, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x72, 0x00, 0x53, 0x00,
            0x4c, 0x00, 0x25, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x4f, 0x00, 0x64, 0x00,
            0x61, 0x00, 0x73, 0x00, 0x24, 0x00, 0x46, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x45, 0x00,
            0x6f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x33, 0x00, 0x38, 0x00, 0x47, 0x00, 0x71, 0x00,
            0x5a, 0x00, 0x37, 0x00, 0x7a, 0x00, 0x35, 0x00, 0x6b, 0x00, 0x3c, 0x00, 0x26, 0x00,
            0x37, 0x00, 0x69, 0x00, 0x75, 0x00, 0x36, 0x00, 0x37, 0x00, 0x47, 0x00, 0x21, 0x00,
            0x2d, 0x00, 0x69, 0x00, 0x37, 0x00, 0x78, 0x00, 0x5f, 0x00, 0x72, 0x00, 0x4b, 0x00,
            0x5c, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x7a, 0x00, 0x49, 0x00, 0x31, 0x00,
            0x5a, 0x00, 0x7b, 0x00, 0x29, 0x00, 0x3b, 0x00, 0x78, 0x00, 0x3b, 0x00, 0x55, 0x00,
            0x3e, 0x00, 0x35, 0x00, 0x2b, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x38, 0x00,
            0x2a, 0x00, 0x59, 0x00, 0x6b, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x6a, 0x00,
            0x49, 0x00, 0x2c, 0x00, 0x79, 0x00, 0x6e, 0x00, 0x35, 0x00, 0x4f, 0x00, 0x49, 0x00,
            0x55, 0x00, 0x35, 0x00, 0x61, 0x00, 0x72, 0x00, 0x77, 0x00, 0x38, 0x00, 0x32, 0x00,
            0x24, 0x00, 0x46, 0x00, 0x32, 0x00, 0x32, 0x00, 0x27, 0x00, 0x64, 0x00, 0x5a, 0x00,
            0x77, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x77, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x63, 0x00,
            0x4f, 0x00, 0x67, 0x00, 0x64, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x30, 0x00,
            0x28, 0x00, 0x2e, 0x00, 0x6f, 0x00, 0x3e, 0x00, 0x59, 0x00, 0x28, 0x00, 0x67, 0x00,
            0x52, 0x00, 0x35, 0x00, 0x5a, 0x00, 0x7c, 0x00, 0x56, 0x00, 0x6a, 0x00, 0x5c, 0x00,
            0x3c, 0x00, 0x30, 0x00, 0x59, 0x00, 0x5c, 0x00, 0x5e, 0x00, 0x38, 0x00, 0x54, 0x00,
            0x5c, 0x00, 0x5b, 0x00, 0x42, 0x00, 0x62, 0x00, 0x70, 0x00, 0x34, 0x00, 0x5c, 0x00,
            0x57, 0x00, 0x7a, 0x00, 0x4b, 0x00, 0x2f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x4f, 0x00,
            0x41, 0x00, 0x33, 0x00, 0x52, 0x00, 0x36, 0x00, 0x27, 0x00, 0x30, 0x00, 0x6d, 0x00,
            0x4a, 0x00, 0x30, 0x00, 0x78, 0x00, 0x46, 0x00, 0x65, 0x00, 0x4e, 0x00, 0x29, 0x00,
            0x66, 0x00, 0x3f, 0x00, 0x72, 0x00, 0x71, 0x00, 0x75, 0x00, 0x4c, 0x00, 0x2b, 0x00,
            0x5c, 0x00, 0x46, 0x00, 0x52, 0x00, 0x7b, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x66, 0x00,
            0x56, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x72, 0x00, 0x61, 0x00, 0x68, 0x00, 0x28, 0x00,
            0x7d, 0x00, 0x58, 0x00, 0x2a, 0x00, 0x7b, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x54, 0x00,
            0x3a, 0x00, 0x26, 0x00, 0x52, 0x00, 0x44, 0x00, 0x60, 0x00, 0x50, 0x00, 0x65, 0x00,
            0x48, 0x00, 0x7d, 0x00, 0x2a, 0x00, 0x74, 0x00, 0x49, 0x00, 0x7b, 0x00, 0x21, 0x00,
            0x61, 0x00, 0x52, 0x00, 0x43, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x74, 0x00, 0x5c, 0x00,
            0x62, 0x00, 0x68, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x2b, 0x00, 0x6f, 0x00, 0x7c, 0x00,
            0x42, 0x00, 0x67, 0x00, 0x32, 0x00, 0x58, 0x00, 0x35, 0x00, 0x30, 0x00, 0x2f, 0x00,
            0x2d, 0x00, 0x60, 0x00, 0x62, 0x00, 0x51, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x31, 0x00,
            0x48, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0x25, 0x00, 0x58, 0x00, 0x4a, 0x00,
            0x76, 0x00, 0x32, 0x00, 0x62, 0x00, 0x27, 0x00, 0x42, 0x00, 0x40, 0x00, 0x53, 0x00,
            0x7c, 0x00, 0x7d, 0x00, 0x50, 0x00, 0x3d, 0x00, 0x40, 0x00, 0x76, 0x00, 0x38, 0x00,
            0x58, 0x00, 0x39, 0x00, 0x63, 0x00, 0x3c, 0x00, 0x5b, 0x00, 0x23, 0x00, 0x53, 0x00,
            0x7a, 0x00, 0x54, 0x00, 0x74, 0x00, 0x61, 0x00, 0x76, 0x00, 0x4a, 0x00, 0x3e, 0x00,
            0x33, 0x00, 0x75, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x48, 0x00, 0x33, 0x00, 0x71, 0x00,
            0x76, 0x00, 0x48, 0x00, 0x71, 0x00, 0x41, 0x00, 0x6f, 0x00, 0x2a, 0x00, 0x67, 0x00,
            0x70, 0x00, 0x21, 0x00, 0x70, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x58, 0x00, 0x68, 0x00,
            0x23, 0x00, 0x39, 0x00, 0x46, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x57, 0x00, 0x3a, 0x00,
            0x79, 0x00, 0x7b, 0x00, 0x6c, 0x00, 0x55, 0x00, 0x33, 0x00, 0x65, 0x00, 0x49, 0x00,
            0x72, 0x00, 0x30, 0x00, 0x4f, 0x00, 0x41, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x4a, 0x00,
            0x60, 0x00, 0x79, 0x00, 0x70, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x75, 0x00, 0x44, 0x00,
            0x59, 0x00, 0x58, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x74, 0x00, 0x51, 0x00,
            0x57, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x23, 0x00, 0x45, 0x00, 0x60, 0x00,
            0x4c, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x74, 0x00, 0x40, 0x00, 0x76, 0x00, 0x75, 0x00,
            0x74, 0x00, 0x56, 0x00, 0x44, 0x00, 0x29, 0x00, 0x62, 0x00, 0x58, 0x00, 0x31, 0x00,
            0x78, 0x00, 0x32, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x6b, 0x00, 0x55, 0x00, 0x72, 0x00,
            0x6f, 0x00, 0x6f, 0x00, 0x4a, 0x00, 0x54, 0x00, 0x7d, 0x00, 0x68, 0x00, 0x3f, 0x00,
            0x28, 0x00, 0x21, 0x00, 0x53, 0x00, 0x48, 0x00, 0x5a, 0x00, 0x34, 0x00, 0x36, 0x00,
            0x35, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x75, 0x00, 0x69, 0x00, 0x23, 0x00, 0x75, 0x00,
            0x55, 0x00, 0x43, 0x00, 0x75, 0x00, 0x2f, 0x00, 0x73, 0x00, 0x62, 0x00, 0x6f, 0x00,
            0x37, 0x00, 0x4e, 0x00, 0x25, 0x00, 0x25, 0x00, 0x21, 0x00, 0x3d, 0x00, 0x3c, 0x00,
            0x71, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x36, 0x00, 0x62, 0x00, 0x63, 0x00,
            0x53, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x61, 0x00, 0x4c, 0x00, 0x28, 0x00, 0x2b, 0x00,
            0x4c, 0x00, 0x4e, 0x00, 0x66, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x43, 0x00, 0x75, 0x00,
            0x45, 0x00, 0x37, 0x00, 0x28, 0x00, 0x56, 0x00, 0x36, 0x00, 0x6a, 0x00, 0x3e, 0x00,
            0x64, 0x00, 0x34, 0x00, 0x6a, 0x00, 0x7d, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x7a, 0x00,
            0x3e, 0x00, 0x75, 0x00, 0x38, 0x00, 0x7b, 0x00, 0x42, 0x00, 0x76, 0x00, 0x29, 0x00,
            0x4c, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x2b, 0x00, 0x51, 0x00,
            0x47, 0x00, 0x22, 0x00, 0x48, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x44, 0x00, 0x5d, 0x00,
            0x59, 0x00, 0x63, 0x00, 0x5c, 0x00, 0x24, 0x00, 0x35, 0x00, 0x34, 0x00, 0x70, 0x00,
            0x69, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(16, dcerpc_state.process_header(&request));
        assert_eq!(1008, dcerpc_state.process_request_pdu(&request[16..]));
    }

    #[test]
    pub fn test_parse_dcerpc() {
        let request: &[u8] = &[
            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x45, 0x00, 0x2c, 0x00,
            0x4d, 0x00, 0x73, 0x00, 0x53, 0x00, 0x59, 0x00, 0x2a, 0x00, 0x4a, 0x00, 0x7a, 0x00,
            0x3e, 0x00, 0x58, 0x00, 0x21, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x41, 0x00, 0x4b, 0x00,
            0x4b, 0x00, 0x3c, 0x00, 0x48, 0x00, 0x24, 0x00, 0x38, 0x00, 0x54, 0x00, 0x60, 0x00,
            0x2d, 0x00, 0x29, 0x00, 0x64, 0x00, 0x5b, 0x00, 0x77, 0x00, 0x3a, 0x00, 0x4c, 0x00,
            0x24, 0x00, 0x23, 0x00, 0x66, 0x00, 0x43, 0x00, 0x68, 0x00, 0x22, 0x00, 0x55, 0x00,
            0x29, 0x00, 0x2c, 0x00, 0x4f, 0x00, 0x5a, 0x00, 0x50, 0x00, 0x61, 0x00, 0x2a, 0x00,
            0x6f, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x68, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x67, 0x00,
            0x68, 0x00, 0x68, 0x00, 0x49, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x72, 0x00, 0x53, 0x00,
            0x4c, 0x00, 0x25, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x4f, 0x00, 0x64, 0x00,
            0x61, 0x00, 0x73, 0x00, 0x24, 0x00, 0x46, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x45, 0x00,
            0x6f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x33, 0x00, 0x38, 0x00, 0x47, 0x00, 0x71, 0x00,
            0x5a, 0x00, 0x37, 0x00, 0x7a, 0x00, 0x35, 0x00, 0x6b, 0x00, 0x3c, 0x00, 0x26, 0x00,
            0x37, 0x00, 0x69, 0x00, 0x75, 0x00, 0x36, 0x00, 0x37, 0x00, 0x47, 0x00, 0x21, 0x00,
            0x2d, 0x00, 0x69, 0x00, 0x37, 0x00, 0x78, 0x00, 0x5f, 0x00, 0x72, 0x00, 0x4b, 0x00,
            0x5c, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x7a, 0x00, 0x49, 0x00, 0x31, 0x00,
            0x5a, 0x00, 0x7b, 0x00, 0x29, 0x00, 0x3b, 0x00, 0x78, 0x00, 0x3b, 0x00, 0x55, 0x00,
            0x3e, 0x00, 0x35, 0x00, 0x2b, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x38, 0x00,
            0x2a, 0x00, 0x59, 0x00, 0x6b, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x6a, 0x00,
            0x49, 0x00, 0x2c, 0x00, 0x79, 0x00, 0x6e, 0x00, 0x35, 0x00, 0x4f, 0x00, 0x49, 0x00,
            0x55, 0x00, 0x35, 0x00, 0x61, 0x00, 0x72, 0x00, 0x77, 0x00, 0x38, 0x00, 0x32, 0x00,
            0x24, 0x00, 0x46, 0x00, 0x32, 0x00, 0x32, 0x00, 0x27, 0x00, 0x64, 0x00, 0x5a, 0x00,
            0x77, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x77, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x63, 0x00,
            0x4f, 0x00, 0x67, 0x00, 0x64, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x30, 0x00,
            0x28, 0x00, 0x2e, 0x00, 0x6f, 0x00, 0x3e, 0x00, 0x59, 0x00, 0x28, 0x00, 0x67, 0x00,
            0x52, 0x00, 0x35, 0x00, 0x5a, 0x00, 0x7c, 0x00, 0x56, 0x00, 0x6a, 0x00, 0x5c, 0x00,
            0x3c, 0x00, 0x30, 0x00, 0x59, 0x00, 0x5c, 0x00, 0x5e, 0x00, 0x38, 0x00, 0x54, 0x00,
            0x5c, 0x00, 0x5b, 0x00, 0x42, 0x00, 0x62, 0x00, 0x70, 0x00, 0x34, 0x00, 0x5c, 0x00,
            0x57, 0x00, 0x7a, 0x00, 0x4b, 0x00, 0x2f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x4f, 0x00,
            0x41, 0x00, 0x33, 0x00, 0x52, 0x00, 0x36, 0x00, 0x27, 0x00, 0x30, 0x00, 0x6d, 0x00,
            0x4a, 0x00, 0x30, 0x00, 0x78, 0x00, 0x46, 0x00, 0x65, 0x00, 0x4e, 0x00, 0x29, 0x00,
            0x66, 0x00, 0x3f, 0x00, 0x72, 0x00, 0x71, 0x00, 0x75, 0x00, 0x4c, 0x00, 0x2b, 0x00,
            0x5c, 0x00, 0x46, 0x00, 0x52, 0x00, 0x7b, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x66, 0x00,
            0x56, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x72, 0x00, 0x61, 0x00, 0x68, 0x00, 0x28, 0x00,
            0x7d, 0x00, 0x58, 0x00, 0x2a, 0x00, 0x7b, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x54, 0x00,
            0x3a, 0x00, 0x26, 0x00, 0x52, 0x00, 0x44, 0x00, 0x60, 0x00, 0x50, 0x00, 0x65, 0x00,
            0x48, 0x00, 0x7d, 0x00, 0x2a, 0x00, 0x74, 0x00, 0x49, 0x00, 0x7b, 0x00, 0x21, 0x00,
            0x61, 0x00, 0x52, 0x00, 0x43, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x74, 0x00, 0x5c, 0x00,
            0x62, 0x00, 0x68, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x2b, 0x00, 0x6f, 0x00, 0x7c, 0x00,
            0x42, 0x00, 0x67, 0x00, 0x32, 0x00, 0x58, 0x00, 0x35, 0x00, 0x30, 0x00, 0x2f, 0x00,
            0x2d, 0x00, 0x60, 0x00, 0x62, 0x00, 0x51, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x31, 0x00,
            0x48, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0x25, 0x00, 0x58, 0x00, 0x4a, 0x00,
            0x76, 0x00, 0x32, 0x00, 0x62, 0x00, 0x27, 0x00, 0x42, 0x00, 0x40, 0x00, 0x53, 0x00,
            0x7c, 0x00, 0x7d, 0x00, 0x50, 0x00, 0x3d, 0x00, 0x40, 0x00, 0x76, 0x00, 0x38, 0x00,
            0x58, 0x00, 0x39, 0x00, 0x63, 0x00, 0x3c, 0x00, 0x5b, 0x00, 0x23, 0x00, 0x53, 0x00,
            0x7a, 0x00, 0x54, 0x00, 0x74, 0x00, 0x61, 0x00, 0x76, 0x00, 0x4a, 0x00, 0x3e, 0x00,
            0x33, 0x00, 0x75, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x48, 0x00, 0x33, 0x00, 0x71, 0x00,
            0x76, 0x00, 0x48, 0x00, 0x71, 0x00, 0x41, 0x00, 0x6f, 0x00, 0x2a, 0x00, 0x67, 0x00,
            0x70, 0x00, 0x21, 0x00, 0x70, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x58, 0x00, 0x68, 0x00,
            0x23, 0x00, 0x39, 0x00, 0x46, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x57, 0x00, 0x3a, 0x00,
            0x79, 0x00, 0x7b, 0x00, 0x6c, 0x00, 0x55, 0x00, 0x33, 0x00, 0x65, 0x00, 0x49, 0x00,
            0x72, 0x00, 0x30, 0x00, 0x4f, 0x00, 0x41, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x4a, 0x00,
            0x60, 0x00, 0x79, 0x00, 0x70, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x75, 0x00, 0x44, 0x00,
            0x59, 0x00, 0x58, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x74, 0x00, 0x51, 0x00,
            0x57, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x23, 0x00, 0x45, 0x00, 0x60, 0x00,
            0x4c, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x74, 0x00, 0x40, 0x00, 0x76, 0x00, 0x75, 0x00,
            0x74, 0x00, 0x56, 0x00, 0x44, 0x00, 0x29, 0x00, 0x62, 0x00, 0x58, 0x00, 0x31, 0x00,
            0x78, 0x00, 0x32, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x6b, 0x00, 0x55, 0x00, 0x72, 0x00,
            0x6f, 0x00, 0x6f, 0x00, 0x4a, 0x00, 0x54, 0x00, 0x7d, 0x00, 0x68, 0x00, 0x3f, 0x00,
            0x28, 0x00, 0x21, 0x00, 0x53, 0x00, 0x48, 0x00, 0x5a, 0x00, 0x34, 0x00, 0x36, 0x00,
            0x35, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x75, 0x00, 0x69, 0x00, 0x23, 0x00, 0x75, 0x00,
            0x55, 0x00, 0x43, 0x00, 0x75, 0x00, 0x2f, 0x00, 0x73, 0x00, 0x62, 0x00, 0x6f, 0x00,
            0x37, 0x00, 0x4e, 0x00, 0x25, 0x00, 0x25, 0x00, 0x21, 0x00, 0x3d, 0x00, 0x3c, 0x00,
            0x71, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x36, 0x00, 0x62, 0x00, 0x63, 0x00,
            0x53, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x61, 0x00, 0x4c, 0x00, 0x28, 0x00, 0x2b, 0x00,
            0x4c, 0x00, 0x4e, 0x00, 0x66, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x43, 0x00, 0x75, 0x00,
            0x45, 0x00, 0x37, 0x00, 0x28, 0x00, 0x56, 0x00, 0x36, 0x00, 0x6a, 0x00, 0x3e, 0x00,
            0x64, 0x00, 0x34, 0x00, 0x6a, 0x00, 0x7d, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x7a, 0x00,
            0x3e, 0x00, 0x75, 0x00, 0x38, 0x00, 0x7b, 0x00, 0x42, 0x00, 0x76, 0x00, 0x29, 0x00,
            0x4c, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x2b, 0x00, 0x51, 0x00,
            0x47, 0x00, 0x22, 0x00, 0x48, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x44, 0x00, 0x5d, 0x00,
            0x59, 0x00, 0x63, 0x00, 0x5c, 0x00, 0x24, 0x00, 0x35, 0x00, 0x34, 0x00, 0x70, 0x00,
            0x69, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request, core::STREAM_TOSERVER)
        );
        if let Some(hdr) = dcerpc_state.header {
            assert_eq!(0, hdr.hdrtype);
            assert_eq!(5, hdr.rpc_vers);
            assert_eq!(1024, hdr.frag_length);
        }
        let tx = &dcerpc_state.transactions[0];
        assert_eq!(11, tx.ctxid);
        assert_eq!(9, tx.opnum);
        assert_eq!(1, tx.first_request_seen);
        assert_eq!(1000, tx.stub_data_buffer_ts.len());
        assert_eq!(true, tx.stub_data_buffer_reset_ts);
    }

    #[test]
    pub fn test_parse_bind_pdu() {
        let bind1: &[u8] = &[
            0x05, 0x00, 0x0b, 0x01, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e,
            0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let bind2: &[u8] = &[
            0x05, 0x00, 0x0b, 0x02, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e,
            0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x67, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(), // TODO ASK if this is correct?
            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
        );
    }

    #[test]
    pub fn test_parse_bind_frag_1() {
        let bind1: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0xc7, 0x70, 0x0d, 0x3e, 0x71, 0x37, 0x39, 0x0d, 0x3a, 0x4f,
            0xd3, 0xdc, 0xca, 0x49, 0xe8, 0xa3, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0xb6, 0x55, 0x75, 0xdb, 0x9e, 0xba, 0x54,
            0x56, 0xd3, 0x45, 0x10, 0xb7, 0x7a, 0x2a, 0xe2, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6e, 0x39, 0x21, 0x24, 0x70, 0x6f,
            0x41, 0x57, 0x54, 0x70, 0xb8, 0xc3, 0x5e, 0x89, 0x3b, 0x43, 0x03, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x39, 0x6a, 0x86, 0x5d,
            0x24, 0x0f, 0xd2, 0xf7, 0xb6, 0xce, 0x95, 0x9c, 0x54, 0x1d, 0x3a, 0xdb, 0x02, 0x00,
            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x12, 0xa5,
            0xdd, 0xc5, 0x55, 0xce, 0xc3, 0x46, 0xbd, 0xa0, 0x94, 0x39, 0x3c, 0x0d, 0x9b, 0x5b,
            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
            0x87, 0x1c, 0x8b, 0x6e, 0x11, 0xa8, 0x67, 0x98, 0xd4, 0x5d, 0xf6, 0x8a, 0x2f, 0x33,
            0x24, 0x7b, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x9b, 0x82, 0x13, 0xd1, 0x28, 0xe0, 0x63, 0xf3, 0x62, 0xee, 0x76, 0x73,
            0xf9, 0xac, 0x3d, 0x2e, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x07, 0x00, 0x01, 0x00, 0xa9, 0xd4, 0x73, 0xf2, 0xed, 0xad, 0xe8, 0x82, 0xf8, 0xcf,
            0x9d, 0x9f, 0x66, 0xe6, 0x43, 0x37, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x2b, 0x85, 0x38, 0x4f, 0x73, 0x96, 0xb1,
            0x73, 0xe1, 0x59, 0xbe, 0x9d, 0xe2, 0x6c, 0x07, 0x05, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
        ];
        let bind2: &[u8] = &[
            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xbf, 0xfa, 0xbb, 0xa4, 0x9e, 0x5c,
            0x80, 0x61, 0xb5, 0x8b, 0x79, 0x69, 0xa6, 0x32, 0x88, 0x77, 0x01, 0x00, 0x01, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x39, 0xa8, 0x2c, 0x39,
            0x73, 0x50, 0x06, 0x8d, 0xf2, 0x37, 0x1e, 0x1e, 0xa8, 0x8f, 0x46, 0x98, 0x02, 0x00,
            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x91, 0x13,
            0xd0, 0xa7, 0xef, 0xc4, 0xa7, 0x96, 0x0c, 0x4a, 0x0d, 0x29, 0x80, 0xd3, 0xfe, 0xbf,
            0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
            0xcc, 0x2b, 0x55, 0x1d, 0xd4, 0xa4, 0x0d, 0xfb, 0xcb, 0x6f, 0x86, 0x36, 0xa6, 0x57,
            0xc3, 0x21, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
            0x01, 0x00, 0x43, 0x7b, 0x07, 0xee, 0x85, 0xa8, 0xb9, 0x3a, 0x0f, 0xf9, 0x83, 0x70,
            0xe6, 0x0b, 0x4f, 0x33, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x0e, 0x00, 0x01, 0x00, 0x9c, 0x6a, 0x15, 0x8c, 0xd6, 0x9c, 0xa6, 0xc3, 0xb2, 0x9e,
            0x62, 0x9f, 0x3d, 0x8e, 0x47, 0x73, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
            0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
        );
        if let Some(ref bind) = dcerpc_state.bind {
            assert_eq!(16, bind.numctxitems);
            assert_eq!(0, dcerpc_state.bytes_consumed); // because the buffer is cleared after a query is complete
        }
    }

    #[test]
    pub fn test_parse_bind_frag_2() {
        let request1: &[u8] = &[
            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let request2: &[u8] = &[0x0D, 0x0E];
        let request3: &[u8] = &[0x0F, 0x10, 0x11, 0x12, 0x13, 0x14];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request3, core::STREAM_TOSERVER)
        );
        let tx = &dcerpc_state.transactions[0];
        assert_eq!(20, tx.stub_data_buffer_ts.len());
    }

    #[test]
    pub fn test_parse_bind_frag_3() {
        let request1: &[u8] = &[
            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
        );
    }

    #[test]
    pub fn test_parse_bind_frag_4() {
        let request1: &[u8] = &[
            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
        );
    }

    #[test]
    pub fn test_parse_dcerpc_frag_1() {
        let fault: &[u8] = &[
            0x05, 0x00, 0x03, 0x03, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xf7, 0x06, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
        ];
        let request1: &[u8] = &[0x05, 0x00];
        let request2: &[u8] = &[
            0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
            0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::err(),
            dcerpc_state.handle_input_data(&fault, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
        );
        let tx = &dcerpc_state.transactions[0];
        assert_eq!(12, tx.stub_data_buffer_ts.len());
    }

    #[test]
    pub fn test_parse_dcerpc_frag_2() {
        let request1: &[u8] = &[
            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let request2: &[u8] = &[0x05, 0x00];
        let request3: &[u8] = &[
            0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
            0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&request3, core::STREAM_TOSERVER)
        );
    }

    #[test]
    pub fn test_parse_dcerpc_back_frag() {
        let bind_ack1: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x48, 0x1a, 0x00, 0x00,
        ];
        let bind_ack2: &[u8] = &[
            0x0c, 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c, 0x6c, 0x73, 0x61, 0x73, 0x73, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        dcerpc_state.data_needed_for_dir = core::STREAM_TOCLIENT;
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack1, core::STREAM_TOCLIENT)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack2, core::STREAM_TOCLIENT)
        );
    }

    #[test]
    // Check if the parser accepts bind pdus that have context ids starting
    // from a non-zero value.
    pub fn test_parse_bind_pdu_ctx_id_non_zero() {
        let bindbuf: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x7f, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        let expected_uuid: &[u8] = &[
            0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x46,
        ];
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bindbuf, core::STREAM_TOSERVER)
        );
        if let Some(ref bind) = dcerpc_state.bind {
            let bind_uuid = &bind.uuid_list[0].uuid;
            assert_eq!(1, bind.uuid_list.len());
            assert_eq!(
                cmp::Ordering::Equal,
                bind_uuid
                    .iter()
                    .zip(expected_uuid)
                    .map(|(x, y)| x.cmp(y))
                    .find(|&ord| ord != cmp::Ordering::Equal)
                    .unwrap_or(bind_uuid.len().cmp(&expected_uuid.len()))
            );
        }
    }

    #[test]
    // Check for endless loop with bind PDUs (Imported from C code)
    pub fn test_parse_bind_pdu_infinite_loop() {
        let bindbuf: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x7f, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02,
            0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
            0x01, 0x02, 0x03, 0x04, 0xFF, /* ka boom - endless loop */
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bindbuf, core::STREAM_TOSERVER)
        );
    }

    #[test]
    // Check for endless loop with bind_ack PDUs (Imported from C code)
    pub fn test_parse_bindack_pdu_infinite_loop() {
        let bind_ack: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7f, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0xfd, 0x04, 0x01, 0x00, 0x04, 0x00, 0x31, 0x33,
            0x35, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x01, 0x02, 0x03, 0x04,
            0xFF,
        ];
        let mut dcerpc_state = DCERPCState::new();
        dcerpc_state.data_needed_for_dir = core::STREAM_TOCLIENT;
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack, core::STREAM_TOCLIENT)
        );
    }

    #[test]
    // Check for correct internal ids for bind_acks
    pub fn test_parse_bindack_internal_ids() {
        let bind1: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x50, 0x08, 0x43, 0x95, 0x43, 0x5a, 0x8b, 0xb2, 0xf4, 0xc5,
            0xb9, 0xee, 0x67, 0x55, 0x7c, 0x19, 0x00, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xda, 0xc2, 0xbc, 0x9b, 0x35, 0x2e, 0xd4, 0xc9,
            0x1f, 0x85, 0x01, 0xe6, 0x4e, 0x5a, 0x5e, 0xd4, 0x04, 0x00, 0x03, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xb2, 0x97, 0xcc, 0x14, 0x6f, 0x70,
            0x0d, 0xa5, 0x33, 0xd7, 0xf4, 0xe3, 0x8e, 0xb2, 0x2a, 0x1e, 0x05, 0x00, 0x02, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x96, 0x4e, 0xa6, 0xf6,
            0xb2, 0x4b, 0xae, 0xb3, 0x21, 0xf4, 0x97, 0x7c, 0xcd, 0xa7, 0x08, 0xb0, 0x00, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xbc, 0xc0,
            0xf7, 0x71, 0x3f, 0x71, 0x54, 0x44, 0x22, 0xa8, 0x55, 0x0f, 0x98, 0x83, 0x1f, 0xfe,
            0x04, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
            0xbe, 0x52, 0xf2, 0x58, 0x4a, 0xc3, 0xb5, 0xd0, 0xba, 0xac, 0xda, 0xf0, 0x12, 0x99,
            0x38, 0x6e, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0xdb, 0xfa, 0x73, 0x01, 0xb3, 0x81, 0x01, 0xd4, 0x7f, 0xa0, 0x36, 0xb1,
            0x97, 0xae, 0x29, 0x7f, 0x01, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x07, 0x00, 0x01, 0x00, 0x89, 0xbe, 0x41, 0x1d, 0x38, 0x75, 0xf5, 0xb5, 0xad, 0x27,
            0x73, 0xf1, 0xb0, 0x7a, 0x28, 0x82, 0x05, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf6, 0x87, 0x09, 0x93, 0xb8, 0xa8, 0x20, 0xc4,
            0xb8, 0x63, 0xe6, 0x95, 0xed, 0x59, 0xee, 0x3f, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x92, 0x77, 0x92, 0x68, 0x3e, 0xa4,
            0xbc, 0x3f, 0x44, 0x33, 0x0e, 0xb8, 0x33, 0x0a, 0x2f, 0xdf, 0x01, 0x00, 0x02, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xa1, 0x03, 0xd2, 0xa9,
            0xd2, 0x16, 0xc9, 0x89, 0x67, 0x18, 0x3e, 0xb1, 0xee, 0x6b, 0xf9, 0x18, 0x02, 0x00,
            0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x2f, 0x09,
            0x5e, 0x74, 0xec, 0xa0, 0xbb, 0xc1, 0x60, 0x18, 0xf1, 0x93, 0x04, 0x17, 0x11, 0xf9,
            0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
            0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
            0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let bind_ack1: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0xc1, 0x2b, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x50,
            0x49, 0x50, 0x45, 0x5c, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x00, 0x0d, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let bind2: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0xc7, 0x70, 0x0d, 0x3e, 0x71, 0x37, 0x39, 0x0d, 0x3a, 0x4f,
            0xd3, 0xdc, 0xca, 0x49, 0xe8, 0xa3, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0xb6, 0x55, 0x75, 0xdb, 0x9e, 0xba, 0x54,
            0x56, 0xd3, 0x45, 0x10, 0xb7, 0x7a, 0x2a, 0xe2, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6e, 0x39, 0x21, 0x24, 0x70, 0x6f,
            0x41, 0x57, 0x54, 0x70, 0xb8, 0xc3, 0x5e, 0x89, 0x3b, 0x43, 0x03, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x39, 0x6a, 0x86, 0x5d,
            0x24, 0x0f, 0xd2, 0xf7, 0xb6, 0xce, 0x95, 0x9c, 0x54, 0x1d, 0x3a, 0xdb, 0x02, 0x00,
            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x12, 0xa5,
            0xdd, 0xc5, 0x55, 0xce, 0xc3, 0x46, 0xbd, 0xa0, 0x94, 0x39, 0x3c, 0x0d, 0x9b, 0x5b,
            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
            0x87, 0x1c, 0x8b, 0x6e, 0x11, 0xa8, 0x67, 0x98, 0xd4, 0x5d, 0xf6, 0x8a, 0x2f, 0x33,
            0x24, 0x7b, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x9b, 0x82, 0x13, 0xd1, 0x28, 0xe0, 0x63, 0xf3, 0x62, 0xee, 0x76, 0x73,
            0xf9, 0xac, 0x3d, 0x2e, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x07, 0x00, 0x01, 0x00, 0xa9, 0xd4, 0x73, 0xf2, 0xed, 0xad, 0xe8, 0x82, 0xf8, 0xcf,
            0x9d, 0x9f, 0x66, 0xe6, 0x43, 0x37, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x2b, 0x85, 0x38, 0x4f, 0x73, 0x96, 0xb1,
            0x73, 0xe1, 0x59, 0xbe, 0x9d, 0xe2, 0x6c, 0x07, 0x05, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xbf, 0xfa, 0xbb, 0xa4, 0x9e, 0x5c,
            0x80, 0x61, 0xb5, 0x8b, 0x79, 0x69, 0xa6, 0x32, 0x88, 0x77, 0x01, 0x00, 0x01, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x39, 0xa8, 0x2c, 0x39,
            0x73, 0x50, 0x06, 0x8d, 0xf2, 0x37, 0x1e, 0x1e, 0xa8, 0x8f, 0x46, 0x98, 0x02, 0x00,
            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x91, 0x13,
            0xd0, 0xa7, 0xef, 0xc4, 0xa7, 0x96, 0x0c, 0x4a, 0x0d, 0x29, 0x80, 0xd3, 0xfe, 0xbf,
            0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
            0xcc, 0x2b, 0x55, 0x1d, 0xd4, 0xa4, 0x0d, 0xfb, 0xcb, 0x6f, 0x86, 0x36, 0xa6, 0x57,
            0xc3, 0x21, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
            0x01, 0x00, 0x43, 0x7b, 0x07, 0xee, 0x85, 0xa8, 0xb9, 0x3a, 0x0f, 0xf9, 0x83, 0x70,
            0xe6, 0x0b, 0x4f, 0x33, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x0e, 0x00, 0x01, 0x00, 0x9c, 0x6a, 0x15, 0x8c, 0xd6, 0x9c, 0xa6, 0xc3, 0xb2, 0x9e,
            0x62, 0x9f, 0x3d, 0x8e, 0x47, 0x73, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
            0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00,
        ];
        let bind_ack2: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0xc2, 0x2b, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x50,
            0x49, 0x50, 0x45, 0x5c, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x00, 0x10, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let bind3: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0xa4, 0x7f, 0x8e, 0xc6, 0xef, 0x56, 0x9b, 0x63, 0x92, 0xfa,
            0x08, 0xb3, 0x35, 0xe2, 0xa5, 0x81, 0x00, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x9f, 0xfc, 0x78, 0xd2, 0x5f, 0x16, 0x0b, 0xbc,
            0xc6, 0xdb, 0x5d, 0xef, 0xde, 0x54, 0xa2, 0x6f, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x78, 0xb8, 0x96, 0xc7, 0x2f, 0xda,
            0x11, 0x6b, 0xd1, 0x28, 0x68, 0xe1, 0xd6, 0x71, 0xac, 0x9d, 0x03, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xcf, 0xf4, 0xd7, 0x37,
            0x03, 0xda, 0xcc, 0xe3, 0x3e, 0x34, 0x7f, 0x67, 0x99, 0x91, 0x41, 0x3d, 0x01, 0x00,
            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x48, 0xeb,
            0x32, 0xf0, 0x27, 0xd5, 0x9d, 0xd0, 0x1e, 0xc6, 0x48, 0x46, 0x97, 0xe9, 0xdb, 0x09,
            0x05, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
            0x82, 0xec, 0x0d, 0x08, 0xf2, 0x8f, 0x22, 0x57, 0x42, 0x9b, 0xce, 0xa8, 0x74, 0x16,
            0xc6, 0xec, 0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x2e, 0x00, 0x70, 0x44, 0xee, 0xc9, 0x30, 0x6b, 0xf4, 0x34, 0x1e, 0x3d,
            0x35, 0x0f, 0xf7, 0xf7, 0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
            0x07, 0x00, 0x01, 0x00, 0x59, 0x04, 0x39, 0x3f, 0x59, 0x87, 0x14, 0x0e, 0x76, 0x8d,
            0x17, 0xc2, 0x47, 0xfa, 0x67, 0x7f, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0xd6, 0xed, 0x2e, 0x57, 0xfa, 0xf4, 0x72,
            0x6c, 0x10, 0x0d, 0xe5, 0x51, 0x7f, 0xd0, 0x39, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d,
            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xea, 0x8b, 0x84, 0x4d, 0x44, 0x43,
            0xc1, 0x94, 0x75, 0xe2, 0x81, 0x48, 0xd8, 0x77, 0xd9, 0xce, 0x05, 0x00, 0x00, 0x00,
            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x89, 0x4f, 0xe7, 0x95,
            0xa3, 0xc1, 0x62, 0x36, 0x26, 0x9e, 0x67, 0xdb, 0x2c, 0x52, 0x89, 0xd3, 0x01, 0x00,
            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x78, 0x56,
            0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
            0x01, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let bind_ack3: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x1a, 0x33, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x70,
            0x69, 0x70, 0x65, 0x5c, 0x73, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x73, 0x00, 0x0c, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let mut dcerpc_state = DCERPCState::new();
        let expected_uuid1 = vec![
            0x4b, 0x32, 0x4f, 0xc8, 0x16, 0x70, 0x01, 0xd3, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
            0xe1, 0x88,
        ];
        let expected_uuid2 = vec![
            0x4b, 0x32, 0x4f, 0xc8, 0x16, 0x70, 0x01, 0xd3, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
            0xe1, 0x88,
        ];
        let expected_uuid3 = vec![
            0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0xab, 0xcd, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67,
            0x89, 0xab,
        ];
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack1, core::STREAM_TOCLIENT)
        );
        if let Some(ref back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            assert_eq!(12, back.accepted_uuid_list[0].ctxid);
            assert_eq!(expected_uuid1, back.accepted_uuid_list[0].uuid);
        }
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack2, core::STREAM_TOCLIENT)
        );
        if let Some(ref back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            assert_eq!(15, back.accepted_uuid_list[0].ctxid);
            assert_eq!(expected_uuid2, back.accepted_uuid_list[0].uuid);
        }
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind3, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(&bind_ack3, core::STREAM_TOCLIENT)
        );
        if let Some(ref back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            dcerpc_state.data_needed_for_dir = core::STREAM_TOSERVER;
            assert_eq!(11, back.accepted_uuid_list[0].ctxid);
            assert_eq!(expected_uuid3, back.accepted_uuid_list[0].uuid);
        }
    }

    #[test]
    pub fn test_bind_acks_alter_contexts_internal_ids() {
        let bind: &[u8] = &[
            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x40, 0xfd, 0x2c, 0x34, 0x6c, 0x3c, 0xce, 0x11, 0xa8, 0x93,
            0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let bindack: &[u8] = &[
            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x7d, 0xd8, 0x00, 0x00, 0x0d, 0x00, 0x5c, 0x70,
            0x69, 0x70, 0x65, 0x5c, 0x6c, 0x6c, 0x73, 0x72, 0x70, 0x63, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];
        let alter_context: &[u8] = &[
            0x05, 0x00, 0x0e, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x01, 0x00, 0xd0, 0x4c, 0x67, 0x57, 0x00, 0x52, 0xce, 0x11, 0xa8, 0x97,
            0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
            0x00, 0x00,
        ];
        let alter_context_resp: &[u8] = &[
            0x05, 0x00, 0x0f, 0x03, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x7d, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
        ];

        let mut dcerpc_state = DCERPCState::new();
        let expected_uuid1 = vec![
            0x34, 0x2c, 0xfd, 0x40, 0x3c, 0x6c, 0x11, 0xce, 0xa8, 0x93, 0x08, 0x00, 0x2b, 0x2e,
            0x9c, 0x6d,
        ];
        let expected_uuid2 = vec![
            0x57, 0x67, 0x4c, 0xd0, 0x52, 0x00, 0x11, 0xce, 0xa8, 0x97, 0x08, 0x00, 0x2b, 0x2e,
            0x9c, 0x6d,
        ];
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(bind, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(bindack, core::STREAM_TOCLIENT)
        );
        if let Some(ref back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            assert_eq!(0, back.accepted_uuid_list[0].ctxid);
            assert_eq!(expected_uuid1, back.accepted_uuid_list[0].uuid);
        }
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(alter_context, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(alter_context_resp, core::STREAM_TOCLIENT)
        );
        if let Some(ref back) = dcerpc_state.bindack {
            assert_eq!(1, back.accepted_uuid_list.len());
            assert_eq!(1, back.accepted_uuid_list[0].ctxid);
            assert_eq!(expected_uuid2, back.accepted_uuid_list[0].uuid);
        }
    }

    #[test]
    pub fn test_parse_dcerpc_frag_3() {
        let request1: &[u8] = &[
            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0c, 0x00,
        ];
        let request2: &[u8] = &[
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
            0x09, 0x0A, 0x0B, 0x0C, 0xFF, 0xFF,
        ];
        let mut dcerpc_state = DCERPCState::new();
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(request1, core::STREAM_TOSERVER)
        );
        assert_eq!(
            AppLayerResult::ok(),
            dcerpc_state.handle_input_data(request2, core::STREAM_TOSERVER)
        );
        let tx = &dcerpc_state.transactions[0];
        assert_eq!(2, tx.opnum);
        assert_eq!(0, tx.ctxid);
        assert_eq!(14, tx.stub_data_buffer_ts.len());
    }
}
